day11 Django: froms组件: 数据校验 显示错误信息 渲染数据 重置数据 自定义规则

徘徊边缘 提交于 2020-03-03 19:09:13
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
 
 
 
 
 
 
 
 
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!