form验证实例
创建项目
django-admin startproject Mydjango
cd Mydjango
python manage.py startapp APP
项目架构
[其它保持默认的忽略未显示]
Mydjango
APP
migrations
0001_initial.py
__init__.py
static
__init__.py
jquery-3.3.1.min.js
templates
add_user.html
edit_user.html
user.html
admin.py
apps.py
models.py
views.py
Mydjango
settings.py
urls.py
db.sqlite3
add_user.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>this from login</title>
<script src="../static/jquery-3.3.1.min.js"></script>
<style>
form i {
color: red;
}
form span {}
#id_gen li{list-style: none; }
</style>
</head>
<body>
<h1>这是添加用户的页面</h1>
<!--加novalidata参数避免浏览器检测 加enctype是上传文件用-->
<form action="add_user.html" method="POST" novalidate enctype="multipart/form-data">
{% csrf_token %}
<!--解释说明:-->
<!--HTML页面生成-->
<!--{{ obj.user }} 从后端数据调取,利用 forms 模块生成 user用户 input标签 其它标签类同-->
<!--错误信息反馈-->
<!--{{ data_obj }} 为传送到后端的所有数据-->
<!--{{ data_obj.user }} 为传送到后端,user 字段的数据-->
<!--{{ data_obj.user.cleaned_data }} 为传送到后端,user 字段验证通过的数据-->
<!--{{ data_obj.user.cleaned_errors }} 为传送到后端,user 字段验证失败的错误信息反馈,可能有多个错误信息-->
<!--{{ data_obj.user.cleaned_errors.0 }} 为传送到后端,user 字段验证失败的错误信息反馈的第一个错误信息-->
<!--其它字段类同-->
<p>{{ data_obj.user.label }}:{{ data_obj.user }}<i>{{ data_obj.user.errors.0 }}</i></p>
<p>{{ data_obj.pwd.label }}:{{ data_obj.pwd }}<i>{{ data_obj.pwd.errors.0 }}</i></p>
<p>{{ data_obj.gen.label }}:{{ data_obj.gen }}</p>
<p>{{ data_obj.area.label }}:{{ data_obj.area }}</p>
<p>{{ data_obj.age.label }}:{{ data_obj.age }}<i>{{ data_obj.age.errors.0 }}</i></p>
<p>{{ data_obj.email.label }}:{{ data_obj.email }}<i>{{ data_obj.email.errors.0 }}</i></p>
<p>{{ data_obj.img.label }}{{ data_obj.img }}<i>{{ data_obj.img.errors.0 }}</i></p>
<span>整体错误信息提示:{{ data_obj.non_field_errors }}</span>
<!-- 后端数据全部以P标签形式生成,可以用 {{ obj.as_p }} 【不建议使用全部生成,不便于页面控制和样式修改】 -->
<p><a><input type="submit" value="提交"></a></p>
</form>
<script>
//所有关于密码的标签类型都变更为 passwors 输入时候密码密文显示
$("p").find("input[name='pwd']").attr("type", "password")
</script>
</body>
</html>
edit_user.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>this from login</title>
<script src="../static/jquery-3.3.1.min.js"></script>
<style>
p {display: block;width: 240px; }
form li{list-style-type: none;}
.errorlist li{color: red; position: absolute;left: 260px;}
</style>
</head>
<body>
<h1>这是编辑中的页面</h1>
<!--加novalidata参数避免浏览器检测-->
{% csrf_token %}
<form action="/edit_user-{{ nid }}.html" method="POST" novalidate>
<!--解释说明:-->
<!--字段信息大部分和添加页面一样,在这里为了展示效果使用添加页面说明过的,一键生成 <p> 标签-->
<!--其它字段类同-->
{{ data_obj.as_p }}
<input type="submit" value="提交">
</form>
</body>
</html>
users.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>this is user list</title>
<script src="../static/jquery-3.3.1.min.js"></script>
<style>
a{cursor:pointer}
table{border:solid 2px #0D3349; text-align: center;}
table tr th {background: #0099CC;color:#fff; padding: 10px;font-size: 18px;}
table tr td {background: #49b5ff;color:#fff; padding: 10px;}
</style>
</head>
<body>
<table id="User_Tab"> <!--定义表格基本属性-->
{% csrf_token %}
<thead> <!--表格标题标签-->
<tr>
<th>序列号</th>
<th>用户名</th>
<th>密码</th>
<th>性别</th>
<th>地区</th>
<th>年龄</th>
<th>邮箱</th>
<th>操作</th>
</tr>
</thead>
<tbody>
{% for row in user_list %}
<tr>
<td>{{ row.id }}</td>
<td>{{ row.user }}</td>
<td>{{ row.pwd }}</td>
{% if row.gen == True %}
<td>女</td>
{% else %}
<td>男</td>
{% endif %}
{% if row.area == "0" %}
<td>华南</td>
{% elif row.area == "1" %}
<td>华北</td>
{% elif row.area == "2" %}
<td>华中</td>
{% elif row.area == "3" %}
<td>华东</td>
{% else %}
<td>华西</td>
{% endif %}
<td>{{ row.age }}</td>
<td>{{ row.email }}</td>
<td><a href="edit_user-{{ row.id }}.html" type="submit">编辑</a>|<a onclick="del_user('{{ row.id }}')">删除</a></td>
</tr>
{% endfor %}
</tbody>
</table>
<script>
function del_user(nid) {
var PostData = {}; //建立空数组,用于存放拿到的数据
PostData["nid"]=nid; //需要删除的数据添加到数组中便于传输到后端处理
$.ajax({
url: '/del_user.html',
type: "GET",
data: PostData,
success: function (arg) {
window.location.reload(); //刷新页面,显示刚添加信息
}
})
}
</script>
</body>
</html>
models.py
# -*- coding:utf8 -*-
from django.db import models
class User_tab(models.Model): #创建用户表
user = models.CharField(max_length=18,) #用户字段
pwd = models.CharField(max_length=32,) #密码字段
gen = models.BooleanField() #性别字段
area = models.CharField(max_length=18,) #地区字段
age = models.IntegerField() #年龄字段
email = models.EmailField() #邮箱字段
views.py
# -*- coding:utf8 -*-
from django.shortcuts import render,redirect,HttpResponse
from APP import models
from django import forms
from django.forms import fields,widgets
from django.core.exceptions import ValidationError
class From_check(forms.Form): #继承forms模块
#利用froms模块进行数据验证,变量名和前端name属性保持一致
# start --------------------------------- forms模块数据验证 ------------------------------
# 【注意,验证字段为了写入数据库方便,需要和数据库中数据字段保持一致!】
# 限制类型-字符串最大长度最小长度,且不能为空
user = fields.CharField(
label="用户",
max_length=18,
min_length=2,
required=True,
error_messages={
'required':'用户名不能为空',
'max_length':'用户名不能超过18个字符',
'min_length':'用户名不能小于2个字符',
}
)
# 限制类型-字符串最小长度为8,且不能为空
pwd = fields.CharField(
label="密码",
max_length=32,
min_length=8,
required=True,
error_messages = {
'required': '密码不能为空',
'max_length': '密码不能超过32个字符',
'min_length': '密码不能小于8个字符',
}
)
gen = fields.ChoiceField(
label="性别",
choices=((0,'男'),(1,'女'),),
initial=0,
widget=widgets.RadioSelect,
error_messages={
'required': '性别是必选项'
}
)
area = fields.ChoiceField(
label="地区",
choices=[(0,'华南'),(1,'华北'),(2,'华中'),(3,'华东'),(4,'华西')],
#如果从数据库中获取choices必须是列表格式,示例写法:【也可以使用ModelChoiceField方式从数据库获取】
#models.User_tab.objects.objects.values_list('id','username')
initial=2,
error_messages={
'required':''
}
)
#配合从数据库调取数据实时更新展现前端页面用法
# def __init__(self, *args,**kwargs):
# super(From_check, self).__init__(*args,**kwargs) #拷贝所有静态属性赋值给fields
# self.fields['area'].widget.choices=models.User_tab.objects.objects.values_list('id','username')
# 限制类型-整型,且不能为空
age = fields.IntegerField(
label="年龄",
max_value=60,
min_value=18,
required=True,
error_messages={
'required': '年龄不能为空',
'max_value':'老爷爷不要玩儿网络啦~',
'min_value':'未成年不能玩儿网络!!!',
'invalid':'年龄格式有问题,必须为数字',
}
)
# 限制类型-邮箱,且不能为空
email = fields.EmailField(
label="邮箱",
required=True,
error_messages={
'required': '邮箱不能为空',
'invalid': '邮箱格式有问题',
}
)
def clean(self): # Django预留扩展验证函数
value_dict = self.cleaned_data # 其他验证通过的数据
v1 = value_dict.get('user') # 拿到验证通过的 username 字段数据,用于再次验证
v2 = value_dict.get('email') # 拿到验证通过的 email 字段数据,用于再次验证
print("验证通过的用户名是:", v1, "邮箱是", v2)
d1 = models.User_tab.objects.filter(user=v1).count() # 获取数据库中用户名出现次数
d2 = models.User_tab.objects.filter(email=v2).count() # 获取数据库中邮箱出现次数
print("数据库获取v1是否存在", d1, "数据库获取v2是否存在", d2)
if d1 != 0 or d2 != 0: # 判断用户名和邮箱在数据库中是否存在
raise ValidationError('此用户或邮箱已经被占用!')
return self.cleaned_data
# end --------------------------------- forms模块数据验证 ------------------------------
def Data_sub(request):
if request.method == "GET":
data_obj = From_check() #经过验证,包含未验证通过的错误信息
return render(request, "add_user.html", {"data_obj": data_obj})
else:
data_obj = From_check(request.POST,request.FILES) #拿到from获取到的所有数据(post数据和file数据)
if data_obj.is_valid(): #判断是否验证成功
print("验证成功:",data_obj.cleaned_data) #已经验证成功后用户的正确数据【字典形式】
models.User_tab.objects.create(**data_obj.cleaned_data) #验证通过的数据写入数据库【使用**数据可避免单个字段写入】
return redirect("/users.html")
else:
print("验证错误:",data_obj.errors) #验证失败返回的错误信息
return render(request,"add_user.html",{"data_obj":data_obj}) #将验证数据传输到前端页面,便于取验证通过的数据和错误反馈信息
def Query_users(request):
user_list = models.User_tab.objects.all()
return render(request, "users.html",{'user_list':user_list,})
def Edit_user(request,nid):
if request.method == "GET":
data = models.User_tab.objects.filter(id=nid).first() #数据库中查询该ID所有字段
print("编辑字段",data)
data_obj = From_check({'user':data.user,'pwd':data.pwd,'age':data.age,'email':data.email,}) #拿到需要编辑的对象
return render(request,"edit_user.html",locals()) #传送前端页面可利用from组件模块生成html
else:
print("获取编辑后的数据:",request.POST.get,nid)
data_obj = From_check(request.POST)
if data_obj.is_valid(): #判断是否验证成功
print("验证成功:",data_obj.cleaned_data) #已经验证成功后用户的正确数据【字典形式】
models.User_tab.objects.filter(id=nid).update(**data_obj.cleaned_data) #验证通过的数据写入数据库【使用**数据可避免单个字段写入】
return redirect("/users.html")
else:
print("验证错误:",data_obj.errors) #验证失败返回的错误信息
return render(request,"edit_user.html",locals()) #将验证数据传输到前端页面,便于取验证通过的数据和错误反馈信息
def Del_user(request):
nid = request.GET .get('nid')
print("删除ID是:",nid)
models.User_tab.objects.filter(id=nid).delete()
return HttpResponse("删除成功!!!")
settings.py
INSTALLED_APPS
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'APP',
]
TEMPLATES
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'APP/templates')],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
STATIC_URL
STATIC_URL = '/static/'
urls.py
# -*- coding:utf8 -*-
from django.contrib import admin
from django.urls import path,re_path
from APP import views
urlpatterns = [
path('admin/', admin.site.urls),
re_path('^add_user.html$',views.Data_sub),
re_path('^users.html$',views.Query_users),
re_path('^edit_user-(\d+).html$',views.Edit_user), #获取编辑的用户id
re_path('^del_user.html$',views.Del_user),
]
生成数据表测试
生成数据表
python manage.py makemigrations APP
python manage.py migrate
运行项目
python manage.py runserver