本文章只是学习笔记,部分资料参考自互联网,图片非原创,仅用于学习理解 !
MVC 与 MTV
MVC - Model View Controller,模型(model)-视图(view)-控制器(controller)的缩写,是软件工程中的一种软件架构模式,Model模型中主要用于存储与数据库相关的字段或数据库通信方面的东西,Controller控制器用于存储URL的分发等,最后的View视图则是完善控制器中的路径分发,每一个路径对应一个view视图函数。
模型(M),控制器(C)和视图(V)三层,他们之间以一种插件式的、松耦合的方式连接在一起:
A.模型负责业务对象与数据库的映射(ORM) B.视图负责与用户的交互(页面) C.控制器接受用户的输入调用模型和视图完成用户的请求
ORM:对象关系映射(Object Relational Mapping,简称ORM,或O/RM,或O/R mapping)
通常情况下我们写代码用的是面向对象的方法,而我们的数据库无法支持面向对象的编程,为了解决两者之间的不同,就出现了ORM映射技术,使用这种技术我们无需关注sql语句的具体编写,只需要使用特定的API即可完成复杂的查询删除等任务,但有一个缺点,采用此技术在一定程度上会消耗系统部分资源,而对于非常复杂的查询工作,还是要使用纯SQL语句来写。
Django的MTV模式本质上和MVC是一样的,也是为了各组件间保持松耦合关系,只是定义上有些许不同,Django的MTV分别是值:
M 代表模型(Model): 负责业务对象和数据库的关系映射(ORM)。 T 代表模板 (Template):负责如何把页面展示给用户(html)。 V 代表视图(View): 负责业务逻辑,并在适当时候调用Model和Template。
除了以上三层之外,还需要一个URL分发器,它的作用是将一个个URL的页面请求分发给不同的View处理,View再调用相应的Model和Template,MTV的响应模式如下所示:
这种设计模式优势在于各组件都是松耦合的。每个由Django驱动的Web应用都有着明确的目的,并且可独立更改而不影响到其它的部分。
HTTP协议:Hyper Text Transfer Protocol(超文本传输协议),是用于万维网服务器与本地浏览器之间传输超文本的传送协议。
该协议是基于TCP/IP的请求协议
HTTP协议规定,请求从客户端发出,最后服务器端响应该请求并 返回。换句话说,肯定是先从客户端开始建立通信的,服务器端在没有 接收到请求之前不会发送响应无状态保存
HTTP是一种不保存状态,即无状态(stateless)协议。HTTP协议自身不对请求和响应之间的通信状态进行保存,协议对于发送过的请求或响应都不做持久化处理。
无连接:无连接的含义是限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接。采用这种方式可以节省传输时间。
HTTP请求方式
GET提交的数据会放在URL之后,以?分割URL和传输数据,参数之间以&相连,POST方法是把提交的数据放在HTTP包的Body中. GET提交的数据大小有限制(因为浏览器对URL的长度有限制),而POST方法提交的数据没有限制. GET与POST请求在服务端获取请求数据方式不同。 GET方式提交数据,会带来安全问题,而POST请求则相对安全。
创建第一个django项目
1.如果是使用Pycharm创建的项目,直接创建项目,即可。
2.如果没有创建app的名字,也可以在进入django目录中,执行 python manage.py startapp MyWeb 命令创建.
更多django shell命令行参数。
python manage.py shell #进入django shell | |
python manage.py dbshell #进入django dbshell | |
python manage.py check #检查django项目完整性 | |
python manage.py flush #清空数据库 | |
python manage.py compilemessages #编译语言文件 | |
python manage.py makemessages #创建语言文件 | |
python manage.py showmigrations #查看生成的数据库同步脚本 | |
python manage.py sqlflush #查看生成清空数据库的脚本 | |
python manage.py sqlmigrate #查看数据库同步的sql语句 | |
python manage.py dumpdata #导出数据 | |
python manage.py loaddata #导入数据 | |
python manage.py diffsettings #查看你的配置和django默认配置的不同之处 |
2.修改settings.py 配置文件,导入我们的app的名字,去掉csrf这个选项
MIDDLEWARE = [ | |
'django.middleware.csrf.CsrfViewMiddleware', # 为了能够开心玩耍,把这个干掉 | |
] | |
INSTALLED_APPS = [ | |
'django.contrib.admin', | |
'django.contrib.auth', | |
'django.contrib.contenttypes', | |
'django.contrib.sessions', | |
'django.contrib.messages', | |
'django.contrib.staticfiles', | |
'MyWeb.apps.MywebConfig' # 导入 | |
] |
3.来urls.py里面写一条路由,名字就叫hello , 映射到views.hello函数下处理此请求。
from MyWeb import views # 导入 | |
urlpatterns = [ | |
path('admin/', admin.site.urls), | |
path('hello/',views.hello) | |
] |
4.最后在myweb里面的views.py设置一个视图函数,最后运行。
from django.shortcuts import HttpResponse | |
# Create your views here. | |
# 这个request必须加,不然会报错 | |
def hello(request): | |
return HttpResponse("<h1>hello lyshark</h1>") |
5.配置好以后,启动django,访问 http://127.0.0.1:8000/ 完成了。
6.如果需要引入静态资源,需要设置一下settings.py
Static files (CSS, JavaScript, Images) | |
https://docs.djangoproject.com/en/3.0/howto/static-files/ | |
# 这个路径是对应 src="/static/ 的别名 | |
如果这个路径改为 STATIC_URL = '/abc/' 那么<script src="/abc/xxx.js"></script> | |
STATIC_URL = '/static/' | |
STATICFILES_DIRS = ( | |
os.path.join(BASE_DIR,'static'), | |
) |
Django 初始化操作
初始化Django:
D:\> pip install django # 安装 | |
D:\> django-admin startproject MyProject # 创建项目 | |
D:\MyProject> django-admin startapp MyWeb # 创建APP | |
D:\MyProject> python manage.py runserver 0.0.0.0:80 # 启动Django | |
D:\MyProject> python manage.py shell # 进入Django交互shell | |
D:\MyProject> python manage.py dbshell # 进入DBShell | |
D:\MyProject> python manage.py check # 检查Django完整性 |
修改一下django的配置文件settings.py
,导入我们生成APP的名字.
MIDDLEWARE = [ | |
'django.middleware.security.SecurityMiddleware', | |
'django.contrib.sessions.middleware.SessionMiddleware', | |
'django.middleware.common.CommonMiddleware', | |
#'django.middleware.csrf.CsrfViewMiddleware', # 注释掉此行 | |
'django.contrib.auth.middleware.AuthenticationMiddleware', | |
] | |
INSTALLED_APPS = [ | |
'django.contrib.admin', | |
'django.contrib.auth', | |
'django.contrib.contenttypes', | |
'django.contrib.sessions', | |
'django.contrib.messages', | |
'django.contrib.staticfiles', | |
'MyWeb.apps.MywebConfig' # 添加此行,导入我们的APP的名字 | |
] |
然会修改urls.py
在这里写一条路由记录.
from MyWeb import views | |
urlpatterns = [ | |
path('admin/', admin.site.urls), | |
path("hello/",views.hello,name="hello") | |
] |
最后我们在views.py
视图函数里添加一条路由.
from django.shortcuts import HttpResponse | |
def hello(request): | |
return HttpResponse("<h1>hello lyshark</h1>") |
有时候我们需要在本地引入JS或者静态资源,此时你需要修改一下Django的setting.py
里面的路径.
Static files (CSS, JavaScript, Images) | |
https://docs.djangoproject.com/en/3.0/howto/static-files/ | |
"/static/lyshark.js"> | 此时我们的默认路径是/static/,那么前端就可以直接调用<script src=|
STATIC_URL = '/static/' | |
STATICFILES_DIRS=( | |
os.path.join(BASE_DIR,'static') | |
) |
Django 模板与视图
简单的路由编写:
urlpatterns = [ | |
path('admin/', admin.site.urls), | |
path('',views.index,name="index"), # 一条访问主站的路由 | |
path('login/id=<int:id>&name=<str:name>',views.login,name="login"), # 名称后面传递参数 | |
path('add/<int:x>/<int:y>/',views.add,name="add") # 路径中传递参数 | |
] | |
from django.shortcuts import render,HttpResponse | |
def index(request): | |
return render(request,"index.html") | |
def login(request, id, name): | |
return HttpResponse("用户ID{} , 用户名{} ".format(id,name)) | |
def add(request,x,y): | |
temp = int(x)+int(y) | |
return HttpResponse("相加结果:{}".format(temp)) |
使用模板传递简单的参数:
**用户名: {{ user }} 密码:{{ pasd }} 标题:{{ title }}:** | |
def index(request): | |
username = "lyshark" | |
password = "123123" | |
title = "hello lyshark" | |
return render(request,"index.html",{"user":username,"pasd":password,"title":title}) |
后端组装数据然后传递给前端:
**用户名: {{ user }} 密码:{{ pasd }} 标题:{{ title }}:** | |
def index(request): | |
username = "admin" | |
password = "123123" | |
title = "hello lyshark" | |
dict = { | |
"user": username, | |
"pasd": password, | |
"title": title | |
} | |
return render(request,"index.html",dict) |
通过info变量遍历出指定字段元素:
**站点名称:{{ info.site }} 站点描述:{{ info.content }}:** | |
def index(request): | |
info = {"site":"blib.cn","content":"hello lyshark"} | |
return render(request,"index.html",{"info":info}) |
通过for语句遍历打印列表数据:
{% for item in total %} | |
**打印数据: {{ item }}:**<br> | |
{% endfor %} | |
def index(request): | |
lists = ["HTML","CSS","JAVASCRIPT","Python","JQuery"] | |
return render(request,"index.html",{"total":lists}) |
通过for语句倒序循环打印:
{% for item in total reversed%} | |
**打印数据: {{ item }}:**<br> | |
{% endfor %} | |
def index(request): | |
lists = ["1","2","3","4","5"] | |
return render(request,"index.html",{"total":lists}) |
通过使用for循环遍历字典:
{% for key,value in info.items %} | |
{{ key }} : {{ value }} | |
{% endfor %} | |
def index(request): | |
info = {"site":"blib.cn","content":"hello lyshark"} | |
info1 = {"site": "blib.cn", "content": "hello admin"} | |
return render(request,"index.html",{"info":info,"info1":info1}) |
简单的路径拼接:
<a href="{{ request.path }}?uid=1">当前网址加参数</a> | |
<!--获取当前路径 拼接成 /add/4/5--> | |
{{ request.path }}{% url 'add' 4 5 %} | |
def add(request,x,y): | |
temp = int(x)+int(y) | |
return HttpResponse("相加结果:{}".format(temp)) | |
def index(request): | |
return render(request,"index.html") |
判断用户是否登录:
{% if request.user.is_authenticated %} | |
{{ request.user.username }},您好! | |
{% else %} | |
请登陆,这里放登陆链接 | |
{% endif %} |
使用if语句判断数据:
{% if username == "lyshark" and password == "123123" %} | |
**恭喜你:** | |
{% elif username == "admin" or password == "123123" %} | |
**欢迎管理员:** | |
{% else %} | |
**这个都不是:** | |
{% endif %} | |
def index(request): | |
username = "admin" | |
password = "123123" | |
return render(request,"index.html",{"username":username,"password":password}) |
if语句也可以判断列表元素:
{% if 1 in list %} | |
**在里面:** | |
{% elif 10 not in list %} | |
** 不在里面:** | |
{% endif %} | |
def index(request): | |
list = [1,2,3,4,5] | |
return render(request,"index.html",{"list":list}) |
最后的大总结:if与for语句的结合:
{% for item in info %} | |
{% if forloop.first %} | |
**开始了:** | |
{% endif %} | |
{{ forloop.counter }} : {{ item }}<br> | |
{% if forloop.last %} | |
**最后了:** | |
{% endif %} | |
{% endfor %} | |
def index(request): | |
list = map(str,range(100)) | |
return render(request,"index.html",{"info":list}) | |
forloop.counter 索引从 1 开始算 | |
forloop.counter0 索引从 0 开始算 | |
forloop.revcounter 索引从最大长度到 1 | |
forloop.revcounter0 索引从最大长度到 0 | |
forloop.first 当遍历的元素为第一项时为真 | |
forloop.last 当遍历的元素为最后一项时为真 | |
forloop.parentloop | |
用在嵌套的 for 循环中,获取上一层 for 循环的 forloop |
常用的过滤器:: 常用的过滤器,有以下几种.
** 列表长度: {{ total | length }}:**<br> | |
** 输出大小: {{ size | filesizeformat }}:**<br> | |
** 输出时间: {{ date | date:"Y-m-d" }}:**<br> | |
** 首字母大写: {{ title | capfirst }}:**<br> | |
** 从字符串中移除hello字符: {{title | cut:"hello" }}:**<br> | |
** 显示字符串第一个元素: {{ total | first }}:**<br> | |
** 显示字符串最后一个元素: {{ total | last }}:**<br> | |
** 大小写转换(upper/lower): {{ title | upper }}:**<br> | |
** 对数据切片: {{ title | slice:"2:-1" }}:**<br> | |
**截断字符:{{ title | truncatechars:5 }}:**<br> | |
**截断单词:{{ title | truncatewords:1 }}:** | |
def index(request): | |
filesize = 10240 | |
title = "hello lyshark" | |
date = datetime.datetime.now() | |
lists = ["1","2","3","4","5"] | |
return render(request,"index.html",{"total":lists,"size":filesize,"date":date,"title":title}) |
自定义过滤器与标签:
1.首先在Django项目下的APP里面,创建一个templatetags
的目录,这个目录名不能变.
MyWeb/ | |
__init__.py | |
models.py | |
templatetags/ | |
__init__.py | |
mysimple.py | |
views.py | |
2.在templatetags
目录下创建任意的py文件,此处我们就创建一个mysimple.py
,并写入以下两条内容.
from django import template | |
from django.utils.safestring import mark_safe | |
register = template.Library() # 此处必须这样写 | |
# simple_tag(自定义标签):不会限制传参,但不支持if | |
def simple_time(var1,var2,var3): | |
temp = int(var1)+int(var2)+int(var3) | |
return temp | |
# filter(自定义过滤器):限制传参2个,但支持if | |
def My_filter(value, arg): | |
# 传递一个参数的过滤器 | |
return str.upper(value) + arg |
3.在我们需要使用自定义过滤器的时候,必须在index.html
中引入这个变量,然后在前端就可以调用了.
# name: views.py | |
def index(request): | |
title = "hello" | |
return render(request,"index.html",{"title":title}) | |
# name: index.html | |
<!--引入自定义的过滤器--> | |
{% load mysimple %} | |
**自定义标签返回数值: {% simple_time 10 20 30 %}:** <!-- 传递多个参数 --> | |
**传递一个参数的过滤器: {{ title | My_filter:'lyshark' }}:** <!-- 传递一个参数 --> |
模板与模板继承:
母板: {% block title %}{% endblock %} | |
子板继承: {% extends "base.html" %} | |
子板中使用其他模板: {% include "xx.html" %} | |
设置标题: {% block title %}{% endblock %} | |
使用CSS资源: {% block css %} {% endblock %} | |
使用JS资源: {% block js %} {% endblock %} |
1.首先创建一个base.html
文件,以作为我们的母版.
<html> | |
<head> | |
<meta charset="UTF-8"> | |
{% block css %}{% endblock %} | |
</head> | |
<body> | |
<div class="pg-body"> | |
<div class="body-menu"> | |
<ul> | |
<li><a href="/user">用户管理</a></li> | |
<li><a href="/hosts">资产管理</a></li> | |
</ul> | |
</div> | |
<div class="body-content"> | |
{% block body %}{% endblock %} <!--占位符,用于填充子版块--> | |
</div> | |
</div> | |
{% block js %}{% endblock %} | |
</body> | |
</html> |
接着我们需要创建一个子板并继承母版,此处我们创建一个hosts.html
这样的文件.
{% extends 'base.html' %} | |
{% block js %} {% endblock %} | |
{% block css %} {% endblock %} | |
{% block body %} | |
<table> | |
{% for item in host %} | |
<tr> | |
<td>{{ item.hostname }}</td> | |
<td>{{ item.port }}</td> | |
</tr> | |
{% endfor %} | |
</table> | |
{% endblock %} |
我们继续创建一个user.html
,同样也是继承base.html
模板.
{% extends 'base.html' %} | |
{% block js %} {% endblock %} | |
{% block css %} {% endblock %} | |
{% block body %} | |
<ul> | |
{% for item in user_list %} | |
<li>{{ item.username }},{{ item.salary }}</li> | |
{% endfor %} | |
</ul> | |
{% endblock %} |
此处我们需要在urls.py
里面写好路由分发.
from django.contrib import admin | |
from django.urls import path | |
from MyWeb import views | |
urlpatterns = [ | |
path('admin/', admin.site.urls), | |
path('',views.index,name="index"), | |
path('hosts/',views.hosts,name="hosts"), | |
path('user/',views.userinfo,name="user") | |
] |
然后写好views.py
中的视图函数,默认我们返回base.html
这个页面.
from django.shortcuts import render | |
from django.shortcuts import HttpResponse | |
def index(request): | |
return render(request,"base.html") | |
def hosts(request): | |
hosts_list = [] | |
for i in range(10): | |
temp = {'hostname':'192.168.1.'+str(i),'port':80} | |
hosts_list.append(temp) | |
return render(request,'hosts.html',{'host':hosts_list}) | |
def userinfo(request): | |
user_list = [] | |
for i in range(10): | |
temp = {'username': 'user' + str(i),'salary':80} | |
user_list.append(temp) | |
return render(request,'user.html',{'user_list':user_list}) |
简单的用户登录:
# name:login.html | |
<!DOCTYPE html> | |
<body lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<title>Title</title> | |
</head> | |
<form action="{% url 'login' %}" method="post"> # 通过模板获取到login的试图 | |
<input type="text" name="username" /> | |
<input type="text" name="password" /> | |
<input type="submit" name="提交"/> | |
</form> | |
</body> | |
</html> | |
# name: urls.py | |
from django.contrib import admin | |
from django.urls import path | |
from MyWeb import views | |
urlpatterns = [ | |
path('admin/', admin.site.urls), | |
path('login/', views.login, name="login") # name是给视图起一个名字 | |
] | |
# name:views.py | |
from django.shortcuts import render,HttpResponse | |
def login(request): | |
if request.method == "GET": | |
return render(request,"index.html") | |
elif request.method == "POST": | |
username = request.POST.get("username") | |
password = request.POST.get("password") | |
return HttpResponse("您提交的用户:{} 密码:{}".format(username,password)) |
Django 表单操作
普通Form表单的提交:
<!-- name:index.html --> | |
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<title>Title</title> | |
</head> | |
<body> | |
<form action="/" method="post"> | |
<p>账号:<input type="text" name="username"><span>{{ error.username }}</span></p> | |
<p>密码:<input type="password" name="password"><span>{{ error.password }}</span></p> | |
<input type="submit" value="提交请求"> | |
</form> | |
</body> | |
</html> | |
# name: views.py | |
from django.shortcuts import render,HttpResponse | |
def index(request): | |
if request.method == "GET": | |
return render(request,"index.html") | |
else: | |
username = request.POST.get("username") | |
password = request.POST.get("password") | |
error = {"username":"","password":""} | |
if len(username) > 10: | |
error["username"]="用户名不能大于10" | |
if len(password) < 5: | |
error["password"] = "密码不能小于5" | |
return render(request,"index.html",{"error":error}) |
实现单项选择框:
<form action="/index/" method="post"> | |
选择A: | |
<select name="tag_select_a"> | |
{% for item in total_a %} | |
<option value = "{{ item }}"> {{ item }} </option> | |
{% endfor %} | |
</select> | |
选择B: | |
<select name="tag_select_b"> | |
{% for item in total_b %} | |
<option value = "{{ item }}"> {{ item }} </option> | |
{% endfor %} | |
</select> | |
<input type="submit" value="提交选择"> | |
</form> | |
def index(request): | |
if request.method == "GET": | |
tag_select_a = ["HTML", "CSS", "JAVASCRIPT", "Python", "JQuery"] | |
tag_select_b = ["MySQL","Oracle","MSSQL"] | |
return render(request, "index.html", {"total_a": tag_select_a,"total_b": tag_select_b}) | |
elif request.method == "POST": | |
select_a = request.POST.get("tag_select_a") | |
select_b = request.POST.get("tag_select_b") | |
return HttpResponse("选择A: {} 选择B: {}".format(select_a,select_b))<b>普通Form表单的提交</b> |
提交账号密码:
<!-- name:index.html --> | |
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<title>Title</title> | |
</head> | |
<body> | |
<form action="/" method="post"> | |
<p>账号:<input type="text" name="username"><span>{{ error.username }}</span></p> | |
<p>密码:<input type="password" name="password"><span>{{ error.password }}</span></p> | |
<input type="submit" value="提交请求"> | |
</form> | |
</body> | |
</html> | |
# name: views.py | |
from django.shortcuts import render,HttpResponse | |
def index(request): | |
if request.method == "GET": | |
return render(request,"index.html") | |
else: | |
username = request.POST.get("username") | |
password = request.POST.get("password") | |
error = {"username":"","password":""} | |
if len(username) > 10: | |
error["username"]="用户名不能大于10" | |
if len(password) < 5: | |
error["password"] = "密码不能小于5" | |
return render(request,"index.html",{"error":error}) |
Form实现登录表单:
<!--name:index.html--> | |
<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<title>Title</title> | |
</head> | |
<body> | |
<form action="/" method="post" novalidate> | |
<p>账号: {{ form.username }} {{ form.username.errors.0 }}</p> | |
<p>密码: {{ form.password }} {{ form.errors.password }}</p> | |
<p>重复: {{ form.RepeatPass }} {{ form.errors.RepeatPass }}</p> | |
<input type="submit" value="提交"> | |
</form> | |
</body> | |
</html> | |
# name:views.py | |
from django.shortcuts import render,HttpResponse | |
from django.forms import Form,fields,widgets | |
from django.core.exceptions import ValidationError | |
class LoginForm(Form): | |
username = fields.CharField( | |
required = True, | |
max_length = 10, | |
error_messages={"required":"该字段不能为空"}, | |
widget=widgets.TextInput(attrs={"placeholder":"请输入用户名","class":"form-control"}) | |
) | |
password = fields.CharField( | |
required = True, | |
max_length=10, | |
error_messages={"required":"密码字段不能为空","min_length":"密码最小长度为5"}, | |
widget=widgets.PasswordInput(attrs={"placeholder":"请输入密码","class":"form-control"}) | |
) | |
RepeatPass = fields.CharField( | |
required=True, | |
max_length=10, | |
error_messages={"required":"密码字段不能为空","min_length":"密码最小长度为5"}, | |
widget=widgets.PasswordInput(attrs={"placeholder":"重复输入密码","class":"form-control"}) | |
) | |
# 自定义方法(局部钩子)密码必须包含字母和数字 | |
def clean_password(self): | |
if self.cleaned_data.get("password").isdigit() or self.cleaned_data.get("password").isalpha(): | |
raise ValidationError("密码必须包含数字和字母") | |
else: | |
return self.cleaned_data["password"] | |
# 自定义方法(全局钩子, 检验两个字段),检验两次密码是否一致 | |
def clean_RepeatPass(self): | |
if self.cleaned_data.get("password") != self.cleaned_data.get("RepeatPass"): | |
raise ValidationError("两次输入密码不正确") | |
else: | |
return self.cleaned_data | |
def index(request): | |
if request.method =="GET": | |
form = LoginForm() | |
return render(request, "index.html", {"form": form}) | |
else: | |
form = LoginForm(request.POST) | |
if form.is_valid(): | |
# username = form.data['username'] | |
data = form.cleaned_data | |
username = data.get("username") | |
password = data.get("password") | |
print(username,password) | |
return render(request, "index.html", {"form": form}) | |
return render(request, "index.html", {"form": form}) |
其他常用Form表单:
<!--name: index.html--> | |
<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<title>Title</title> | |
</head> | |
<body> | |
<form action="/" method="post"> | |
{% for field in form %} | |
<p>{{ field.label_tag }} {{ field }} {{ field.errors.0 }}</p> | |
{% endfor %} | |
<input type="submit" value="提交" /> | |
</form> | |
</body> | |
</html> | |
# name: views.py | |
from django.shortcuts import render,HttpResponse | |
from django.forms import Form,fields,widgets | |
class MyForm(Form): | |
hobby = fields.ChoiceField( | |
label="单选框:", | |
required=True, | |
initial=1, # 默认选择1号 | |
choices=( (1,"篮球"),(2,"足球"),(3,"乒乓球"),(4,"滚球")), | |
widget=widgets.RadioSelect() | |
) | |
select = fields.ChoiceField( | |
label="单选框(默认):", | |
required=True, | |
initial=1, | |
choices=( (1,"篮球"),(2,"足球"),(3,"乒乓球"),(4,"滚球")), | |
widget=widgets.Select() | |
) | |
multiple = fields.MultipleChoiceField( | |
label="复选框", | |
choices=((1, "篮球"), (2, "足球"), (3, "羽毛球"), (4, "排球")), | |
initial=[2, 4], | |
widget=widgets.SelectMultiple() | |
) | |
checkbox = fields.ChoiceField( | |
label="单项复选框", | |
initial="checked", # 默认为勾选 | |
widget=widgets.CheckboxInput() | |
) | |
multselect = fields.MultipleChoiceField( | |
label="多项复选框", | |
choices=((1, "篮球"), (2, "足球"), (3, "羽毛球"), (4, "排球")), | |
initial=[1, 3], | |
widget=widgets.CheckboxSelectMultiple() | |
) | |
data = fields.DateField( | |
label="选择日期", | |
widget = widgets.DateInput(attrs={"type":"date"}) | |
) | |
def index(request): | |
if request.method=="GET": | |
form = MyForm() | |
return render(request,"index.html",{"form":form}) | |
else: | |
form = MyForm(request.POST) | |
if form.is_valid(): | |
data = form.cleaned_data | |
print(data.get("hobby")) | |
return HttpResponse("hello lyshark") |
Form实现用户注册:
<!--name: index.html--> | |
<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<title>Title</title> | |
</head> | |
<body> | |
<div> | |
<form action="/" method="post"> | |
<p>{{ form.username.label }} {{ form.username }}</p> | |
<p>{{ form.password.label }} {{ form.password }}</p> | |
<p>{{ form.mobile.label }} {{ form.mobile }} </p> | |
<p>{{ form.email.label }} {{ form.email }} </p> | |
<p>{{ form.text }} </p> | |
<p><input type="submit" value="提交请求"></p> | |
</form> | |
</div> | |
</body> | |
</html> | |
# name: models.py | |
from django.db import models | |
class User(models.Model): | |
id = models.AutoField(primary_key=True) | |
username = models.CharField(max_length=64) | |
password = models.CharField(max_length=32) | |
mobile = models.CharField(max_length=32) | |
email = models.EmailField(max_length=64) | |
text = models.CharField(max_length=128) | |
# name: views.py | |
from django.shortcuts import render,HttpResponse | |
from MyWeb import models | |
from django.forms import Form,fields,widgets | |
from django.core.validators import RegexValidator | |
from django.core.exceptions import ValidationError | |
class UserForm(Form): | |
username = fields.CharField( | |
label = "账号: ", # 给表单加一个标签 | |
required = True, # 不允许字段为空值 | |
min_length=4, # 设置最小长度 | |
max_length = 10, # 设置最大长度 | |
validators=[ RegexValidator(r'^[0-9a-zA-Z]+$',"用户账号只能使用,0-9a-z") ], | |
error_messages={"required":"该字段不能为空","invalid":"无效的用户名", | |
"min_length":"最小长度为5","max_length":"最大长度为10"}, | |
widget=widgets.TextInput(attrs={"placeholder":"请输入用户名","class":"form-control"}) | |
) | |
password = fields.CharField( | |
label = "密码: ", | |
required = True, | |
min_length=5, | |
max_length=10, | |
error_messages={"required":"密码字段不能为空","min_length":"密码最小长度为5"}, | |
widget=widgets.PasswordInput(attrs={"placeholder":"请输入密码","class":"form-control"}) | |
) | |
mobile = fields.CharField( | |
label = "手机: ", | |
required=True, | |
validators=[RegexValidator('[0-9]', "手机号必须是数字")], | |
error_messages={"required":"该字段不能为空"}, | |
widget=widgets.TextInput(attrs={"placeholder": "手机号","class": "form-control"}) | |
) | |
email = fields.EmailField( | |
label="邮箱: ", | |
required=True, | |
error_messages={"required":"邮箱不能为空!!","invalid":"无效的邮箱"}, | |
widget=widgets.EmailInput(attrs={"placeholder": "邮箱", "class": "form-control"}) | |
) | |
text = fields.CharField( | |
required=True, | |
widget=widgets.Textarea(attrs={"placeholder": "畅言,欢迎留言...", "class": "form-control", | |
"style":"margin: 0px; width: 203px; height: 98px;"}) | |
) | |
def index(request): | |
if request.method =="GET": | |
form = UserForm() | |
return render(request, "index.html", {"form": form}) | |
else: | |
form = UserForm(request.POST) | |
if form.is_valid(): | |
# username = form.data['username'] | |
data = form.cleaned_data | |
username = data.get("username") | |
is_exits = models.User.objects.filter(username="admin").count() | |
if is_exits != 0: | |
return HttpResponse("您注册的用户已存在") | |
else: | |
models.User.objects.create(**data) | |
return HttpResponse("恭喜您的账号注册完成了") | |
else: | |
return render(request, "index.html", {"form": form.errors}) | |
return render(request, "index.html", {"form": form}) |
实现用户验证:
index.html
<head> | |
<meta charset="UTF-8"> | |
<script src="https://code.jquery.com/jquery-3.1.1.min.js"></script> | |
</head> | |
<body> | |
<form action="/" method="post"> | |
<p> {{ form.email }}</p> | |
<p> {{ form.code }} <a id="fetch_code" class="fetch-code" href="javascript:void(0);">获取验证码</a></p> | |
<input type="submit" value="提交"> | |
</form> | |
<script type="text/javascript"> | |
$("#fetch_code").click(function(){ | |
var email = $("#email").val(); // 获取到用户邮箱 | |
if(email.trim().length != 0) | |
{ | |
$("#fetch_code").empty(); | |
$("#fetch_code").text("发送成功"); | |
$.ajax({ | |
url:"/send_msg/", | |
type:"POST", | |
data:{email:email}, | |
dataType:"json", | |
success:function(recv){ | |
} | |
}) | |
} | |
}) | |
</script> |
models.py
from django.db import models | |
class SendMsg(models.Model): | |
id = models.AutoField(primary_key=True) | |
code = models.CharField(max_length=6) | |
email = models.CharField(max_length=32, db_index=True) | |
count = models.IntegerField(default=0) | |
times = models.IntegerField(default=0) | |
class UserInfo(models.Model): | |
id = models.AutoField(primary_key=True) | |
username = models.CharField(max_length=32, unique=True) | |
password = models.CharField(max_length=32) | |
email = models.CharField(max_length=32, unique=True) |
views.py
from django.shortcuts import render,HttpResponse | |
from django.core.mail import send_mail, send_mass_mail, EmailMultiAlternatives | |
import re,time,random | |
from MyWeb import models | |
def SendMail(rand,user): | |
title = "本次注册验证码是: {} 十分钟以内有效.".format(rand) | |
ret = send_mail("Django 邮件通知",title,"smtpwho@163.com",[user]) | |
if ret: | |
return 1 | |
return 0 | |
def send_msg(request): | |
if request.method=="POST": | |
email = request.POST.get("email") | |
ret = re.match(r'^[0-9a-zA-Z\_\-]+(\.[0-9a-zA-Z\_\-]+)*@[0-9a-zA-Z]+(\.[0-9a-zA-Z]+){1,}$', email) | |
if ret == None: | |
print("不合法") | |
else: | |
ret = models.UserInfo.objects.filter(email=email).count() | |
if ret == 1: | |
print("你的邮箱已经注册了,请换一个..") | |
else: | |
ret = models.SendMsg.objects.filter(email=email).count() # 查询出如果存在sendmsg表里,则不能让其注册 | |
if ret !=0: | |
print("等待超时,暂时不嫩注册..") | |
times = int(time.time()) | |
if times >=models.SendMsg.objects.filter(email=email).values("times"): | |
print(times) | |
else: | |
print("时间还没到") | |
else: | |
rand = random.randint(10000,20000) | |
if SendMail(rand,email): | |
times = int(time.time()+60) # 一分钟只能注册一次 | |
models.SendMsg.objects.create(email=email,code=rand,times=times) | |
return render(request,"reg.html") | |
def reg(request): | |
if request.method == "POST": | |
email = request.POST.get("email") | |
code = request.POST.get("code") | |
ret = models.SendMsg.objects.filter(email=email).values("email","code")[0] | |
if ret['email']==email and ret['code']==code: | |
print("正确了") | |
username = request.POST.get("username") | |
password = request.POST.get("password") | |
ret = models.UserInfo.objects.filter(username=username).count() | |
if ret == 0: | |
# 等于0说明没有这个用户,可以注册 | |
models.UserInfo.objects.create(username=username,password=password,email=email) | |
print("注册完成了") | |
else: | |
print("这个账号重复了,请换一个...") | |
else: | |
print("验证码错误") | |
return render(request, "reg.html") |
urls.py
from django.contrib import admin | |
from django.urls import path | |
from MyWeb import views | |
urlpatterns = [ | |
path('admin/', admin.site.urls), | |
path("reg/",views.reg), | |
path("send_msg/",views.send_msg) | |
] |
settings.py
STATIC_URL = '/static/' | |
EMAIL_USER_TLS = True | |
EMAIL_PORT = 25 | |
EMAIL_HOST = "smtp.163.com" | |
EMAIL_HOST_USER = "smtpwho@163.com" | |
EMAIL_HOST_PASSWORD = "123456789" |
重写父类方法: 通过form表单重写init方法,实现数据库动态添加,前端动态显示,以两个选择框为例
# name: models.py | |
from django.db import models | |
class DBHost(models.Model): | |
id = models.AutoField(primary_key=True) | |
host = models.CharField(max_length=32) | |
title = models.CharField(max_length=32) | |
# name:index.html | |
{{ form.title }} | |
{{ form.host }} | |
# name:views.py | |
from django.shortcuts import render | |
from django.forms import Form,fields,widgets | |
from MyWeb import models | |
class DBHost(Form): | |
title = fields.IntegerField(widget=widgets.Select(choices=[])) | |
host = fields.IntegerField(widget=widgets.SelectMultiple(choices=[])) | |
# 重写父类的 __init__ 方法 | |
def __init__(self,*args,**kwargs): | |
super(DBHost, self).__init__(*args,**kwargs) | |
self.fields['title'].widget.choices = models.DBHost.objects.all().values_list("id","title") | |
self.fields['host'].widget.choices = models.DBHost.objects.all().values_list("id", "host") | |
def index(request): | |
form = DBHost() | |
return render(request,"index.html",{"form":form}) |
给Form表单返回数据: Form表单可以返回默认数据,我们可以通过编号查询到指定数据的默认参数,并返回到编辑框中.
# name:views.py | |
from django.shortcuts import render | |
from django.forms import Form,fields,widgets | |
from MyWeb import models | |
class MyForm(Form): | |
host = fields.CharField(required=True,widget=widgets.TextInput()) | |
title = fields.CharField(required=True, widget=widgets.TextInput()) | |
def index(request): | |
nid = request.GET.get("id") # 通过ID获取到记录 | |
qset = models.DBHost.objects.filter(id=nid).values("host","title") | |
dic = qset[0] # 转为字典 | |
form = MyForm(dic) # 传递到前端编辑框中 | |
return render(request,"index.html",{"form":form}) |