day11 Django: froms组件: 数据校验 显示错误信息 渲染数据 重置数据 自定义规则
一.Django: forms组件
1.forms组件的校验数据功能
1.1.基本语法
1.1.1.新建forms组件类
from django import forms
class BookForm(forms.Form): #创建一个forms的类
title = forms.CharField(max_length=32)
price = forms.IntegerField()
email = forms.EmailField()
1.1.2.命令行测试语法
from app01.views import BookForm
#1.验证不通过示例
fm = BookForm({'title':'bajie','price':2000,'email':'163'}) #实例化
fm.is_valid() #做验证: 这步必须有, 否则验证正确和错误的键值拿不到
Out[5]: False
fm.cleaned_data #正确的键值
Out[6]: {'title': 'bajie', 'price': 2000}
fm.errors #不正确的键值
Out[7]: {'email': ['Enter a valid email address.']}
#2.验证通过示例
fm = BookForm({'title':'bajie','price':2000,'email':'163@163.com'}) #实例化: 注意: 键值对可以多, 但是不能少, 也不能把键搞错
fm.is_valid() #做验证
Out[9]: True
fm.cleaned_data #正确的键值
Out[10]: {'title': 'bajie', 'price': 2000, 'email': '163@163.com'}
fm.errors #不正确的键值
Out[11]: {}
1.2.注册示例(使用form表单)
用户名: 长度不能少于5位, 密码: 是纯数字, 邮箱: 必须符合格式
如果输入数据格式有问题, 显示给用户
models.py
from django.db import models
# Create your models here.
class UserInfo(models.Model):
user = models.CharField(max_length=32)
pwd = models.CharField(max_length=32)
email = models.CharField(max_length=32)
urls.py
from django.contrib import admin
from django.urls import path
from app01 import views
urlpatterns = [
path('admin/', admin.site.urls),
path('register/', views.register),
path('login/', views.login),
]
views.py
from django.shortcuts import render, HttpResponse
from django import forms
from app01.models import UserInfo
# Create your views here.
class UserForm(forms.Form):
msg = {"required": "该字段不能为空", "invalid": "格式错误"}
user = forms.CharField(min_length=5, error_messages=msg) #form表单里面的name要和forms的key一样才行: 为空时显示的内容,必须叫这个名字
pwd = forms.IntegerField()
email = forms.EmailField(error_messages=msg)
def login(request):
return render(request, 'login.html', locals())
def register(request):
if request.method == 'POST':
fm = UserForm(request.POST)
if fm.is_valid():
UserInfo.objects.create(**fm.cleaned_data)
return HttpResponse('ok')
else:
print("cleaned_data: ", fm.cleaned_data)
print("errors: ", fm.errors)
print(type(fm.errors)) #<class 'django.forms.utils.ErrorDict'>可以理解成是一个字典
print(type(fm.errors.get('user'))) #<class 'django.forms.utils.ErrorList'>可以理解成是一个列表
# print(type(fm.errors.get('user')[0])) #取出错误字段的错误信息
errors = fm.errors
return render(request, 'register.html', locals())
else:
return render(request, 'register.html', locals())
templates > register.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="" method="post">
{% csrf_token %}
<p>用户名: <input type="text" name="user"><span>{{ errors.user.0 }}</span></p>
<p>密码: <input type="password" name="pwd"><span>{{ errors.pwd.0 }}</span></p>
<p>邮箱: <input type="text" name="email"><span>{{ errors.email.0 }}</span></p>
<input type="submit">
</form>
</body>
</html>
2.forms组件的页面显示错误信息
3.渲染页面和重置数据
register.html需要我们自己写, 不然呢?
而且会把forms组件的属性加到标签里面: 比如: minlenght = 5, 前端可以给我们检验不挺好吗? 是的, 但是万一检验不了呢,如IE, 所以我们要在后端做校验.
告诉前端不要你做校验: <form action="" method="post" novalidate>
而且实现了: 提交后, 正确的内容不消失, 错误的才清空:
方式一: forms组件帮我们写, 只能帮我们渲染input,但不包括type='submit'的input(包括输入框前面的User; Pwd; Email)
views.py
def register(request):
if request.method == 'POST':
fm = UserForm(request.POST)
if fm.is_valid():
UserInfo.objects.create(**fm.cleaned_data)
return HttpResponse('ok')
else:
print("cleaned_data: ", fm.cleaned_data)
print("errors: ", fm.errors)
print(type(fm.errors))
print(type(fm.errors.get('user')))
# print(type(fm.errors.get('user')[0]))
errors = fm.errors
return render(request, 'register.html', locals())
else:
fm = UserForm()
return render(request, 'register.html', locals())
register.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="" method="post" novalidate>
{% csrf_token %}
{{ fm.as_p }}
<input type="submit">
</form>
</body>
</html>
方式二: 只替换 input 标签
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="" method="post" novalidate>
{% csrf_token %}
<p>用户名: {{ fm.user }}<span>{{ errors.user.0 }}</span></p>
<p>密码: {{ fm.pwd }}<span>{{ errors.pwd.0 }}</span></p>
<p>邮箱: {{ fm.email }}<span>{{ errors.email.0 }}</span></p>
<input type="submit">
</form>
</body>
</html>
方式二: 只替换 input 标签, 在forms组件里设置标签的属性
views.py
class UserForm(forms.Form):
msg = {"required": "该字段不能为空", "invalid": "格式错误"}
user = forms.CharField(min_length=5,
error_messages=msg,
widget=widgets.TextInput(attrs={"class": "form-control"}))
pwd = forms.IntegerField(widget=widgets.PasswordInput(attrs={"class": "form-control"}))
email = forms.EmailField(error_messages=msg,
widget=widgets.EmailInput(attrs={"class": "form-control"}))
register.html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Bootstrap 101 Template</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<h1>注册界面</h1>
<div class="container">
<div class="row">
<div class="col-md-6">
<form action="" method="post" novalidate>
{% csrf_token %}
<p>用户名: {{ fm.user }}<span>{{ errors.user.0 }}</span></p>
<p>密码: {{ fm.pwd }}<span>{{ errors.pwd.0 }}</span></p>
<p>邮箱: {{ fm.email }}<span>{{ errors.email.0 }}</span></p>
<input type="submit">
</form>
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/jquery@1.12.4/dist/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/js/bootstrap.min.js"></script>
</body>
</html>
方式三: 这个方式应该是你喜欢的
方式一的简单但不灵活
方式二的灵活但不简单
views.py
class UserForm(forms.Form):
msg = {"required": "该字段不能为空", "invalid": "格式错误"}
user = forms.CharField(min_length=5,
error_messages=msg,
label="用户名",
widget=widgets.TextInput(attrs={"class": "form-control"}))
pwd = forms.IntegerField(label="密码",
widget=widgets.PasswordInput(attrs={"class": "form-control"}))
email = forms.EmailField(error_messages=msg,
label="邮箱",
widget=widgets.EmailInput(attrs={"class": "form-control"}))
register.html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Bootstrap 101 Template</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<h1>注册界面</h1>
<div class="container">
<div class="row">
<div class="col-md-6">
<form action="" method="post" novalidate>
{% csrf_token %}
{% for field in fm %}
<div class="form-group">
<label for="">{{ field.label }}</label>
{{ field }} <span>{{ field.errors.0 }}</span>
</div>
{% endfor %}
<input type="submit">
</form>
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/jquery@1.12.4/dist/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/js/bootstrap.min.js"></script>
</body>
</html>
4.自定义规则: 钩子的简单使用
4.1.用户名不能重复
4.2.密码不能是纯数字
class UserForm(forms.Form):
msg = {"required": "该字段不能为空", "invalid": "格式错误"}
user = forms.CharField(min_length=5,
error_messages=msg,
label="用户名",
widget=widgets.TextInput(attrs={"class": "form-control"}))
pwd = forms.CharField(label="密码",
widget=widgets.PasswordInput(attrs={"class": "form-control"}))
email = forms.EmailField(error_messages=msg,
label="邮箱",
widget=widgets.EmailInput(attrs={"class": "form-control"}))
def clean_user(self):
val = self.cleaned_data.get('user')
rst = UserInfo.objects.filter(user=val)
if not rst:
return val
else:
raise ValidationError('用户名不能重复')
def clean_pwd(self):
val = self.cleaned_data.get('pwd')
if val.isdigit():
raise ValidationError('密码不能是纯数字')
else:
return val
来源:https://www.cnblogs.com/aiaii/p/12403892.html