django中的forms组件(权限信息校验,增删改查)

时间:2021-02-21 16:35:51

1.用处

  1、用户请求数据验证

  2、自动生成错误信息

  3、打包用户提交的正确信息

  4、如果其中有一个错误了,其他的正确,则保留上次输入的内容

  5、自动创建input标签并可以设置样式

  6.基于forms实现增删改查

2.使用方法

对于注册信息进行校验

在应用下创建一个forms.py文件(起什么名无所谓,后面在视图函数中直接导入进来使用)

from django import forms
from django.forms import widgets
from django.core.exceptions import NON_FIELD_ERRORS, ValidationError class UserInfo(forms.Form):
username = forms.CharField(
required=True, # 标明是必填字段,不能为空
min_length=4, max_length=12,
label="姓名", # 给定字段名称,直接把username换成了姓名
error_messages={"required": "用户名不能为空!!"},
widget=widgets.TextInput(attrs={"placeholder": "用户名", "class": "form-control"}) # 自动生成input框
) password = forms.CharField(
widget=widgets.PasswordInput(attrs={"placeholder":"密码","class":"form-control"}),
label="密码",
) sec_pwd = forms.CharField(
required=True,
label="二次密码",
widget=widgets.PasswordInput(attrs={"placeholder":"二次密码","class":"form-control"})
) age = forms.IntegerField(
label="年龄",
widget = widgets.NumberInput(attrs={"placeholder":"年龄","class":"form-control"}),
error_messages={"required": "输入不对!!"},
) email = forms.EmailField(
widget=widgets.EmailInput(attrs={"placeholder":"邮箱","class":"form-control"}),
label="邮箱",
error_messages={"invalid": "格式错误"}
) # 定制化二次错误信息 # 局部钩子
# 注意这里必须是以clean_ 开头,可以查看源码,下面得到的val都是字符串类型
def clean_username(self):
val = self.cleaned_data.get("username")
if not val.isdigit():
return val
else:
raise ValidationError("用户名非纯数字") def clean_password(self):
val = self.cleaned_data.get("password")
if len(val) > 3:
return val
else:
raise ValidationError("密码太短") def clean_age(self):
val = self.cleaned_data.get("age")
if int(val) > 18:
return val
else:
raise ValidationError("岁数太小") # 全局钩子
# 对于两次输入的密码进行校验是否一致
def clean(self):
password = self.cleaned_data.get("password")
sec_pwd = self.cleaned_data.get("sec_pwd")
if password == sec_pwd:
return self.cleaned_data
else:
raise ValidationError("两次密码不一致")

  这个类到底干了什么事呢??你在解释器中打印就会发现,第一件事就是将自己显示成HTML。form对象做的第二件事就是来校验信息

  调用任何绑定form的is_valid()方法,就可以知道它的数据是否合法

  Django的form系统自动寻找匹配的函数方法,该方法名称以 clean_ 开头,并以字段名称结束。 如果有这样的方法,它将在校验时被调用。这属于一次额外校验

  如果存在异常,我们抛出一个 forms.ValidationError 型异常,这个异常的描述会被作为错误列表中的一项显示给用户

views.py

from django.shortcuts import render,HttpResponse
# Create your views here.
from app01.form import UserInfo def index(request):
# 定制化提示信息,
if request.method=="POST":
form = UserInfo(request.POST)
# 如果全部输入信息有效
if form.is_valid():
return HttpResponse("添加成功")
else:
# 打印输入的信息
print("---",form.cleaned_data) # 得到一个字典
print("???",form.errors) # ErrorDict : {"校验错误的字段":["错误信息",]}
print("!!!",form.errors.get("email")) # ErrorList ["错误信息",] g_error = form.errors.get("__all__")
print("+++",g_error) # <ul class="errorlist nonfield"><li>两次密码不一致</li></ul>
if g_error:
g_error = g_error[0] # 直接获取你自己的错误提示,即两次密码不一致 return render(request, "index.html", locals()) else:
form = UserInfo()
return render(request, "index.html", locals())

这里form.py和创建的视图函数衔接关键点就在于 form = UserInfo(request.POST)

模板渲染:

方式一:

以p标签的样式展现出来,当然也能以能table标签展示

index.html

<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
.error {
color: red;
}
</style>
<link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.css">
</head>
<body>
<h3>注册用户</h3>
<div class="container">
<div class="row">
<div class="col-md-8 col-md-offset-2">
{# 这个novalidate很重要啊,没有这个后面自己定制的错误提示无法渲染出来 #}
{# 自己编写表单验证插件的时候,使用它可以避免和默认的表单验证冲突 #}
<form action="" method="post" novalidate>
{% csrf_token %}
{{ form.as_p }}
<input type="submit">
</form>

</div>
</div>
</div> </body>
</html>

# 要注意这里form表单中添加的属性novalidate,它能够避免和默认的表单验证发生冲突

方式二:

书写相对麻烦

<form action="" method="post" novalidate>
{% csrf_token %}
<div>
<p>姓名</p>
{{ form.username }}
</div>
<div>
<p>密码</p>
{{ form.password }}
</div>
<div>
<p>二次密码</p>
{{ form.sec_pwd }}
</div>
<div>
<p>年龄</p>
{{ form.age }}
</div>
<div>
<p>年龄</p>
{{ form.email }}
</div>
<input type="submit"> </form>

方式三(常用):

<form action="" method="post" novalidate>
{% csrf_token %}
{% for foo in form %}
<div class="form-group">
{# 渲染出lable标签,标签后面是输入框 #}
<lable>{{ foo.label }}</lable>{{ foo }}
{# 专门定制报错信息 #}
<span class="error pull-right">{{ foo.errors.0 }}</span>
{# 对于二次输入报错信息进行设置 #}
{% if foo.label == "二次密码" %}
<span class="error pull-right">{{ g_error|default_if_none:"" }}</span>
{% endif %}
</div>
{% endfor %}
<input type="submit" class="btn btn-default btn-sm">
</form>

3.基于forms组件的ModelForm实现的增删改查

models.py

from django.db import models

class Depart(models.Model):
caption = models.CharField(max_length=32) def __str__(self):
return self.caption
class Role(models.Model):
title = models.CharField(max_length=32) def __str__(self):
return self.title class User(models.Model): name = models.CharField(verbose_name='姓名',max_length=32)
depart = models.ForeignKey(verbose_name='部门',to='Depart',on_delete=models.CASCADE) gender_choices = (
(1,'男'),
(2,'女'),
)
gender = models.IntegerField(verbose_name='性别',choices=gender_choices,default=1) roles = models.ManyToManyField(verbose_name='角色',to='Role')

urls.py

from django.contrib import admin
from django.urls import path,re_path
from app01 import views
urlpatterns = [
path('admin/', admin.site.urls),
re_path('user/list/$', views.user_list),
re_path('user/add/$', views.user_add),
re_path('user/edit/(?P<uid>\d+)/$', views.user_edit),
re_path('user/del/(?P<uid>\d+)/$', views.user_del),
]

views.py

from django.shortcuts import render,redirect
from app01 import models def user_list(request):
user_queryset = models.User.objects.all()
return render(request,'user_list.html',{'user_queryset':user_queryset}) from django import forms
class UserForm(forms.ModelForm):
class Meta:
model = models.User
fields = '__all__'
# fields = ['name','depart']
widgets = {
'name':forms.TextInput(attrs={'class':'form-control'}),
'depart':forms.Select(attrs={'class':'form-control'}),
'gender':forms.Select(attrs={'class':'form-control'}),
'roles':forms.SelectMultiple(attrs={'class':'form-control'}),
}
error_messages = {
'name':{
'required':'用户名不能为空'
}
} def user_add(request):
if request.method == "GET":
form = UserForm()
else:
form = UserForm(request.POST)
if form.is_valid():
print('通过验证')
form.save()
return redirect('/user/list/')
return render(request,'user_add.html',{'form':form}) def user_edit(request,uid):
obj = models.User.objects.filter(id=uid).first()
if request.method =='GET':
form = UserForm(instance=obj)
return render(request,'user_edit.html',{'form':form})
else:
form = UserForm(data=request.POST,instance=obj)
if form.is_valid():
form.save()
return redirect('/user/list/')
else:
return render(request, 'user_edit.html', {'form': form}) def user_del(request,uid):
models.User.objects.filter(id=uid).delete()
return redirect('/user/list/')

user_list.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container">
<a href="/user/add/" class="btn btn-primary">添加</a>
<table class="table table-bordered">
<thead>
<tr>
<th>名称</th>
<th>性别</th>
<th>部门</th>
<th>角色</th>
<th>操作</th>
</tr>
</thead>
<tbody>
{% for row in user_queryset %}
<tr>
<td>{{ row.name }}</td>
<td>{{ row.get_gender_display }}</td>
<td>{{ row.depart.caption }}</td>
<td>
{% for node in row.roles.all %}
<span>{{ node.title }}</span>
{% endfor %}
</td>
<td>
<a href="/user/edit/{{ row.id }}/">编辑</a>
<a href="/user/del/{{ row.id }}/">删除</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</body>
</html>

user_edit.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<h1>编辑用户</h1>
<form method="post" novalidate>
{% csrf_token %}
{% for field in form %}
<div>{{ field.label }}{{ field }} {{ field.errors.0 }}</div>
{% endfor %}
<input type="submit" value="提交">
</form>
</body>
</html>

user_add.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container">
<h1>添加用户</h1>
<form method="post" class="form-horizontal" novalidate>
{% csrf_token %}
{% for field in form %}
<div class="form-group">
<label class="col-sm-2 control-label">{{ field.label }} </label>
<div class="col-sm-10">
{{ field }} {{ field.errors.0 }}
</div>
</div>
{% endfor %}
<input type="submit" value="提交">
</form>
</div>
</body>
</html>

效果:

django中的forms组件(权限信息校验,增删改查)

这里其他效果:

django中的forms组件(权限信息校验,增删改查)