Django中的Form表单验证

回忆一下Form表单验证的逻辑:

前端有若干个input输入框,将用户输入内容,以字典传递给后端。

后端预先存在一个Form表单验证的基类,封装了一个检测用户输入是否全部通过的方法。该方法会先定义好错误信息的字典,并会遍历类的所有属性(对应前端待验证的输入域),调用各自的验证方法,将错误信息(两类,必要与否以及格式正确与否)存入字典,并得出最终的验证结果。在使用时,需要定义继承自Form基类不同的Form类,以对应有着不同输入域的Form表单。在拿到前端给的字典前,要先初始化自定义From类,直接执行封装好的整体验证方法,拿到结果后就可以抛给前端了。

Django中Form表单验证涉及到的知识:

1.Django中的ErrorDcit类如何封装了错误信息

# project/app01/forms.py

from django import forms

# 继承自Django的Form类
# 内部以字段形式定义验证域
class MyForm(forms.Form):
    user = forms.CharField()
    pwd = forms.CharField()
# project/app01/views.py
def form(request):
    from app01.forms import MyForm
    if request.method == 'POST':
        f = MyForm(request.POST)
        ret = f.is_valid()  # bool
        data = f.cleaned_data  # {'user': 'asd', 'pwd': 'asd'}
        errors = f.errors  # ErrorDict,打印时因为__str__方法,会显示位ul标签的形式
        print(errors.get('user', None)[0] if errors.get('user', None) else None)  # ErrorList,以索引取出第一条错误信息
        return render(request, "form.html", {"errors": f.errors})
    return render(request, "form.html")
# project/templates/forms.html        
<form action="/form/" method="post">
    <div>
        用户名:<input type="text" name="user"/>
    </div>
    <div>
        密码:<input type="password" name="pwd"/>
    </div>
    <div>
        <input type="submit" value="提交"/>
    </div>
    {{ errors }}
    <div></div>

 

2.抛给前端的ErrorDcit及使用模板语言漂合理展示

   展示错误信息的前端布局

   通过返回Form类和模板语言在前端动态生成input标签

# project/app01/views.py
def form(request):
    from app01.forms import MyForm
    empty_form = MyForm()
    if request.method == 'POST':
        f = MyForm(request.POST)
        if f.is_valid():
            print(f.cleaned_data)
            # 这里只是为了使得正确提交后不至于让input消失,实际坏境中这里应该是用户信息验证 
            return render(request, "form.html", {'myform': empty_form})
        return render(request, "form.html", {"errors": f.errors, "myform": f})
    else:
        return render(request, "form.html", {'myform': empty_form})
# project/templates/forms.html    
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
    .input-group{
        padding: 15px;
    }
    .input-group input{
        width: 200px;
    }
    .input-group span{
        display: inline-block;
        position: relative;
        border: 1px solid red;
        top: 25px;
        left: -211px;
    }

    </style>
</head>
<body>
    <form action="/form/" method="post">
        <div class="input-group">
            <div style="float:left;width:70px;">用户名:</div>
            {{ myform.user }}
            {% if errors.user.0 %}
            <span>{{ errors.user.0 }}</span>
            {% endif %}
        </div>
        <div class="input-group">
            <div style="float:left;width:70px;">密码:</div>
            {{ myform.pwd }}
            {% if errors.pwd.0 %}
            <span>{{ errors.pwd.0 }}</span>
            {% endif %}
        </div>
        <div>
            <input style="float:left;margin-left:15px;" type="submit" value="提交"/>
        </div>
    </form>

4.django.forms中的CharField参数

(required, min/max_length,error_messages,forms.widget)

   不重启服务时数据库数据动态更新到前端(静态字段的特点)

   field不合需求时自定义验证规则(validators参数)

   

# project/app01/forms.py
    
from django import forms
from app01 import models


def mobile_validate(value):
    import re
    mobile_re = re.compile("^(13[0-9]|14[579]|15[0-3,5-9]|1 6[6]|17[0135678]|18[0-9]|19[89])\\d{8}$")
    if not mobile_re.match(value):
        print('123123')
        raise forms.ValidationError('手机号码格式不对哦')


class MyForm(forms.Form):

    def __init__(self, *args, **kwargs):
        super(MyForm, self).__init__(*args, **kwargs)
        self.fields['book_type'] = forms.CharField(
            widget=forms.Select(choices=models.BookType.objects.values_list('id', 'caption'))
        )

    user = forms.CharField(min_length=4, max_length=10, widget=forms.TextInput)
    pwd = forms.CharField(error_messages={'required': '为什么不输入密码??'})
    email = forms.EmailField(error_messages={'required': '邮箱还没输入哦', 'invalid': '邮箱格式错误'})
    # book_type_choices = (
    #     (0, '小说'),  value
    #     (1, '科普'),  innerText
    # )  # 元组内有元组
    # 从数据库获得数据

    # 注意这里filed都是静态字段
    # 类的静态字段只创建一次以后不会再修改,新的对象都会使用同一份数据
    # 所以MyForm这里的静态字段只会执行一次
    # 加入数据库中的数据更新了,服务器不重启的话,这里从数据库取来的值是不会变的
    # 因此将该字段写入类的初始化方法里,不要忘了执行父类的初始化方法哦
    # book_type_choices = models.BookType.objects.values_list('id', 'caption')
    # book_type = forms.CharField(
    #     widget=forms.Select(choices=book_type_choices)
    # )
    comment = forms.CharField(
        widget=forms.Textarea(attrs={'style': 'border:1px solid red;'})
    )  # 可以为生成的标签添加属性

    mobile = forms.CharField(
        validators=[mobile_validate, ],
        error_messages={'required': '手机号不填不行'},
        widget=forms.TextInput
    )
<div class="input-group">
            <div style="float:left;width:70px;">用户名:</div>
            {{ myform.user }}
            {% if errors.user.0 %}
            <span>{{ errors.user.0 }}</span>
            {% endif %}
        </div>
        <div class="input-group">
            <div style="float:left;width:70px;">密码:</div>
            {{ myform.pwd }}
            {% if errors.pwd.0 %}
            <span>{{ errors.pwd.0 }}</span>
            {% endif %}
        </div>
        <div class="input-group">
            <div style="float:left;width:70px;">邮箱:</div>
            {{ myform.email }}
            {% if errors.email.0 %}
            <span>{{ errors.email.0 }}</span>
            {% endif %}
// 以下都是上面input-group标签的重复,只是field不同而已,不再细说

 碎碎念:

中间给render传入两个字典,一直调试不出问题,费时颇久,下次留心。

posted @ 2018-04-23 22:59  F君君  阅读(1443)  评论(0编辑  收藏  举报