Django学习之Form表单

    form是用于验证用户请求数据合法性的一个组件,Django的Form主要功能

生成HTML标签
验证用户数据(显示错误信息)
HTML Form提交保留上次提交数据
初始化页面显示内容
1、创建一个验证用户请求的模板
    class MyForm(forms.Form):
            user = forms.CharField(...)
     类:模版,到底验证几个
     字段:用于验证用户某个字段
     插件:user = forms.CharField(..,widget=Input框)
2、获取用户请求,进行验证:
     - is_valid()
     - clean()
     - errors
3、
    Form提交:
        errors.字段.0
    Ajax提交:
        errors.as_json()
        errors.as_data()
        {‘user’: [Django对象(),]}
Django的Form的实现步骤

 

登录通过Form实现

"""
django forms 使用练习
"""

from django.shortcuts import render
from django.shortcuts import redirect
from django.shortcuts import HttpResponse
import json
from datetime import date
from datetime import datetime
from django import forms

class LoginForm(forms.Form):
    # 模版中的元素  error_messages自定义错误提示信息
    user = forms.CharField(min_length=6,error_messages={"required": '用户名不能为空','min_length': '用户名长度不能小6'})
    email = forms.EmailField(error_messages={"required": '邮箱不能为空','invalid': '邮箱格式错误'})


class IndexForm(forms.Form):
    # 模版中的元素
    user = forms.CharField(min_length=6,error_messages={"required": '用户名不能为空','min_length': '用户名长度不能小6'})
    email = forms.EmailField(error_messages={"required": '邮箱不能为空','invalid': '邮箱格式错误'})
    favor = forms.MultipleChoiceField(
        choices=[(1,'上海'),(2,'北京'),(3,'深圳')]
    )

def formindex(request):
    #obj = IndexForm()
    #设置默认值
    obj = IndexForm({'user': 'root', 'email': 'root@live.com', 'favor': [2, 3]})
    return render(request,'formindex.html',{'obj': obj})

def formlogin(request):
    if request.method == "GET":
        obj = LoginForm()
        return render(request,'formlogin.html',{'oo': obj})
    elif request.method == "POST":
        obj = LoginForm(request.POST)
        """
        #print(obj)
        #<tr><th><label for="id_user">User:</label></th><td><input type="text" name="user" value="123456" minlength="6" required id="id_user"></td></tr>
        #<tr><th><label for="id_email">Email:</label></th><td><input type="email" name="email" value="11@qq.com" required id="id_email"></td></tr>
        #print(type(obj)) #<class 'app01.views.LoginForm'>
        #验证 user和email验证都通过status才等于True否则等于False
        status = obj.is_valid()
        #获取正确信息
        sucess_obj = obj.clean()
        #获取错误信息
        error_obj = obj.errors
        #print(sucess_obj,type(sucess_obj))  #{'user': '123456'} sucess_obj是类 <class 'dict'>
        #print(error_obj,type(error_obj))   #<ul class="errorlist"><li>email<ul class="errorlist"><li>Enter a valid email address.</li></ul></li></ul> error_obj是类 <class 'django.forms.utils.ErrorDict'>
        """
        if obj.is_valid():
            #所有字段均验证通过获取用户输入的信息
            value_dict = obj.clean()
            print(value_dict)
            # create(**value_dict)
        else:
            #如果用户输入某个字段验证通过,obj.errors['user']会报KeyError  因为'user'键不存在
            #print(obj.errors['user'][0]) #用户名长度不能小6
            #print(obj.errors['email'][0]) #邮箱格式错误
            pass
    return render(request, 'formlogin.html',{"oo":obj})
views.py
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="formlogin" method="post">
    {% csrf_token %}

    <div>
        <!--<input id="user" type="text" name="user">-->
        <!--根据form自动生成html标签-->
        {{ oo.user }}
        <!--如有错误显示错误信息-->
        <span>{{ oo.errors.user.0 }}</span>
    </div>

    <div>
        <!--<input id="pwd" type="text" name="email">-->
        {{ oo.email }}
        <span>{{ oo.errors.email.0 }}</span>
    </div>

    <div>
        <label></label>
        <input type="submit" value="登录">

    </div>
</form>

</body>
</html>
formlogin.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <p>{{ obj.user }}</p>
    <p>{{ obj.email }}</p>
    <p>{{ obj.favor }}</p>
</body>
</html>
formindex.html

 

 ajax使用form

def formajax(request):
    if request.method == "GET":
        return render(request, 'formajax.html')
    elif request.method == "POST":
        ret = {'status': True, 'error':None, 'data': None}
        obj = LoginForm(request.POST)
        if obj.is_valid():
            print(obj.clean())
        else:
            # 方式一
            """
            res_str = obj.errors.as_json() # res_str是一个字符串
            #print(res_str,type(res_str))  #{"user": [{"message": "\u7528\u6237\u540d\u957f\u5ea6\u4e0d\u80fd\u5c0f6", "code": "min_length"}]} <class 'str'>
            ret['status'] = False
            ret['error'] = res_str
        return HttpResponse(json.dumps(ret))
            """
            # 两次反序列化
            # 方式二:
            ret['status'] = False
            ret['error'] = obj.errors.as_data() # {'user': [ValidationError(['用户名长度不能小6'])], 'email': [ValidationError(['邮箱格式错误'])]}
            print(ret['error'])
            # 一次反序列化
        return HttpResponse(json.dumps(ret,cls=JsonCustomEncoder))


#自己定义类 当使用json.dumps时如果被转换对象中有不对的类型对该类型转换
from django.core.validators import ValidationError
class JsonCustomEncoder(json.JSONEncoder):
    def default(self, field):
        if isinstance(field, ValidationError):
            return {'code': field.code, 'message': field.message}
        else:
            return json.JSONEncoder.default(self, field)
views.py
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
        <p>
            {{ oo.user }}
            <span>{{ oo.errors.user.0 }}</span>

        </p>
        <p>
            {{ oo.email }}
            <span>{{ oo.errors.email.0 }}</span>
        </p>
        <p>
        <input id="ajax_submit" type="button" value="Ajax提交"  />
    <script src="/static/jquery-3.1.1.js"></script>
    <script>
        $(function () {

            $('#ajax_submit').click(function () {
                $.ajax({
                    url:"/formajax",
                    data: {user:'root', email: 'root@live.com', pwd: '123123'},
                    type: 'POST',
                    success:function (arg) {
                        alert(arg)
                    }
                })

            })

        })
    </script>
</body>
</html>
formajax.html

 

Form类

    创建Form类时,主要涉及到 【字段】 和 【插件】,字段用于对用户请求数据的验证,插件用于自动生成HTML;

Field
    required=True,               是否允许为空
    widget=None,                 HTML插件
    label=None,                  用于生成Label标签或显示内容
    initial=None,                初始值
    help_text='',                帮助信息(在标签旁边显示)
    error_messages=None,         错误信息 {'required': '不能为空', 'invalid': '格式错误'}
    show_hidden_initial=False,   是否在当前插件后面再加一个隐藏的且具有默认值的插件(可用于检验两次输入是否一直)
    validators=[],               自定义验证规则
    localize=False,              是否支持本地化
    disabled=False,              是否可以编辑
    label_suffix=None            Label内容后缀
 
 
CharField(Field)
    max_length=None,             最大长度
    min_length=None,             最小长度
    strip=True                   是否移除用户输入空白
 
IntegerField(Field)
    max_value=None,              最大值
    min_value=None,              最小值
 

 
 
BaseTemporalField(Field)
    input_formats=None          时间格式化   
 
DateField(BaseTemporalField)    格式:2015-09-01
TimeField(BaseTemporalField)    格式:11:12
DateTimeField(BaseTemporalField)格式:2015-09-01 11:12
 
DurationField(Field)            时间间隔:%d %H:%M:%S.%f
    ...
 
RegexField(CharField)
    regex,                      自定制正则表达式
    max_length=None,            最大长度
    min_length=None,            最小长度
    error_message=None,         忽略,错误信息使用 error_messages={'invalid': '...'}
 
EmailField(CharField)      
    ...
 
FileField(Field)
    allow_empty_file=False     是否允许空文件
 
ImageField(FileField)      
    ...
    注:需要PIL模块,pip3 install Pillow
    以上两个字典使用时,需要注意两点:
        - form表单中 enctype="multipart/form-data"
        - view函数中 obj = MyForm(request.POST, request.FILES)
 
URLField(Field)
    ...

 
ChoiceField(Field)
    ...
    choices=(),                选项,如:choices = ((0,'上海'),(1,'北京'),)
    required=True,             是否必填
    widget=None,               插件,默认select插件
    label=None,                Label内容
    initial=None,              初始值
    help_text='',              帮助提示
 
 
ModelChoiceField(ChoiceField)
    ...                        django.forms.models.ModelChoiceField
    queryset,                  # 查询数据库中的数据
    empty_label="---------",   # 默认空显示内容
    to_field_name=None,        # HTML中value的值对应的字段
    limit_choices_to=None      # ModelForm中对queryset二次筛选
     
FilePathField(ChoiceField)     文件选项,目录下文件显示在页面中
    path,                      文件夹路径
    match=None,                正则匹配
    recursive=False,           递归下面的文件夹
    allow_files=True,          允许文件
    allow_folders=False,       允许文件夹
    required=True,
    widget=None,
    label=None,
    initial=None,
    help_text=''
 
Django内置字段
TextInput(Input)
NumberInput(TextInput)
EmailInput(TextInput)
URLInput(TextInput)
PasswordInput(TextInput)
HiddenInput(TextInput)
Textarea(Widget)
DateInput(DateTimeBaseInput)
DateTimeInput(DateTimeBaseInput)
TimeInput(DateTimeBaseInput)
CheckboxInput
Select
NullBooleanSelect
SelectMultiple
RadioSelect
CheckboxSelectMultiple
FileInput
ClearableFileInput
MultipleHiddenInput
SplitDateTimeWidget
SplitHiddenDateTimeWidget
SelectDateWidget
Django内置插件
# 单radio,值为字符串
# user = fields.CharField(
#     initial=2,
#     widget=widgets.RadioSelect(choices=((1,'上海'),(2,'北京'),))
# )
 
# 单radio,值为字符串
# user = fields.ChoiceField(
#     choices=((1, '上海'), (2, '北京'),),
#     initial=2,
#     widget=widgets.RadioSelect
# )
 
# 单select,值为字符串
# user = fields.CharField(
#     initial=2,
#     widget=widgets.Select(choices=((1,'上海'),(2,'北京'),))
# )
 
# 单select,值为字符串
# user = fields.ChoiceField(
#     choices=((1, '上海'), (2, '北京'),),
#     initial=2,
#     widget=widgets.Select
# )
 
# 多选select,值为列表
# user = fields.MultipleChoiceField(
#     choices=((1,'上海'),(2,'北京'),),
#     initial=[1,],
#     widget=widgets.SelectMultiple
# )
 
 
# 单checkbox
# user = fields.CharField(
#     widget=widgets.CheckboxInput()
# )
 
 
# 多选checkbox,值为列表
# user = fields.MultipleChoiceField(
#     initial=[2, ],
#     choices=((1, '上海'), (2, '北京'),),
#     widget=widgets.CheckboxSelectMultiple
# )
常用选择插件
在使用选择标签时,需要注意choices的选项可以从数据库中获取,但是由于是静态字段 ***获取的值无法实时更新***,那么需要自定义构造方法从而达到此目的
from django.forms import Form
from django.forms import widgets
from django.forms import fields
from django.core.validators import RegexValidator


class InitialForm(DForms.Form):
    username = fields.CharField()
    user_type = fields.IntegerField(
        widget=widgets.Select(choices=[])
    )

    def __init__(self,*args, **kwargs):
        # 执行父类的构造方法
        super(InitialForm,self).__init__(*args, **kwargs)

        self.fields['user_type'].widget.choices = models.UserType.objects.all().values_list('id','caption')
View Code
from django.forms import Form
from django.forms import widgets
from django.forms import fields
from django.core.validators import RegexValidator
 
class MyForm(Form):
    user = fields.CharField(
        validators=[RegexValidator(r'^[0-9]+$', '请输入数字'), RegexValidator(r'^159[0-9]+$', '数字必须以159开头')],
    )
自定义验证规则

 

posted @ 2019-11-15 14:55  泉love水  阅读(172)  评论(0编辑  收藏  举报