【python】-- Django Form

 Django  Form

Django的Form主要具有一下几大功能:

  • 生成HTML标签
  • 验证用户数据(显示错误信息)
  • HTML Form提交保留上次提交数据
  • 初始化页面显示内容(自定义样式)

一、Form 简单示例:

1、view中创建Form类并进行函数处理

from django import forms  # 导入forms
class FM(forms.Form):
    user = forms.CharField()
    pwd = forms.CharField()
    email = forms.EmailField()

def fm(request):
    if request.method == "GET":
        obj = FM()
        return render(request, 'fm.html', {'obj': obj})
    elif request.method == "POST":
        # 获取用户所有数据
        # 每条数据请求的验证
        # 成功:获取所有的正确的信息
        # 失败:显示错误信息
        obj = FM(request.POST)  # 生成from表单验证对象实例
        r1 = obj.is_valid()   # 获取obj对象是否有效
        if r1:
            # obj.cleaned_data
            print(r1)
            print(obj.changed_data)

        else:
            print(r1)
            print(obj.errors.as_json())
            # 错误信息字典形式
            #  {"user": [{"message": "This field is required.", "code": "required"}],
            #  "pwd": [{"message": "This field is required.", "code": "required"}],
            #  "email": [{"message": "This field is required.", "code": "required"}]}
            print(obj.errors['user'][0])
        return redirect("/fm/")

2、生成HTML

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
    <form action="/fm/" method="POST">
        {% csrf_token %}
{#        <!--第一种 input框形式-->#}
{#        <p><input type="text" name="user"/>  {{ obj.errors.user.0 }}</p> <!--user pwd email 必须要跟视图中的继承forms.Form类中的相应实例名称一致-->#}
{#        <p><input type="text" name="pwd"/>   {{ obj.errors.pwd.0 }}</p>#}
{#        <p><input type="text" name="email"/> {{ obj.errors.email.0 }}</p>#}
        <!--第二种 obj.user框形式-->
        <p>{{ obj.user }} {{ obj.errors.user.0 }}</p>  <!-- 类似于view视图中的 obj.errors['user'][0]-->
        <p>{{ obj.pwd }} {{ obj.errors.pwd.0 }}</p>
        <p>{{ obj.email }}{{ obj.errors.email.0 }}</p>

{#        <!--第三种 obj.as_p、obj.as_ul、 obj.as_table(需要在外面添加table标签)框形式,生成方便,自定义样式不强-->#}
{#          {{ obj.as_p }}#}
{#          {{ obj.as_ul }}#}
{#            <table>#}
{#          {{ obj.as_table }}#}
{#            </table>#}
        <input type="submit" value="提交" />
    </form>
</body>
</html>

 

 

二、Form类

 创建Form类时,主要涉及到 fields【字段】 和 wiegets【插件】,功能特性:字段用于对用户请求数据的验证,插件用于自动生成HTML(保留上一次提交的数据)。使用场景:1、在新url方式操作时,字段和插件都需要用到,因为在from提交之后,页面也会被刷新,而插件可以保留上一次的提交数据。2、在用Ajax请求操作时,可以只用到字段的验证功能,因为Ajax请求页面不会刷新,上一次提交数据仍然保留在页面,当然在用Ajax请求操作时也可以使用插件。

1、Django内置字段如下:

  1 Field
  2     required=True,               是否允许为空
  3     widget=None,                 HTML插件
  4     label=None,                  用于生成Label标签或显示内容
  5     initial=None,                初始值
  6     help_text='',                帮助信息(在标签旁边显示)
  7     error_messages=None,         错误信息 {'required': '不能为空', 'invalid': '格式错误'}
  8     show_hidden_initial=False,   是否在当前插件后面再加一个隐藏的且具有默认值的插件(可用于检验两次输入是否一直)
  9     validators=[],               自定义验证规则
 10     localize=False,              是否支持本地化
 11     disabled=False,              是否可以编辑
 12     label_suffix=None            Label内容后缀
 13  
 14  
 15 CharField(Field)
 16     max_length=None,             最大长度
 17     min_length=None,             最小长度
 18     strip=True                   是否移除用户输入空白
 19  
 20 IntegerField(Field)
 21     max_value=None,              最大值
 22     min_value=None,              最小值
 23  
 24 FloatField(IntegerField)
 25     ...
 26  
 27 DecimalField(IntegerField)
 28     max_value=None,              最大值
 29     min_value=None,              最小值
 30     max_digits=None,             总长度
 31     decimal_places=None,         小数位长度
 32  
 33 BaseTemporalField(Field)
 34     input_formats=None          时间格式化   
 35  
 36 DateField(BaseTemporalField)    格式:2015-09-01
 37 TimeField(BaseTemporalField)    格式:11:12
 38 DateTimeField(BaseTemporalField)格式:2015-09-01 11:12
 39  
 40 DurationField(Field)            时间间隔:%d %H:%M:%S.%f
 41     ...
 42  
 43 RegexField(CharField)
 44     regex,                      自定制正则表达式
 45     max_length=None,            最大长度
 46     min_length=None,            最小长度
 47     error_message=None,         忽略,错误信息使用 error_messages={'invalid': '...'}
 48  
 49 EmailField(CharField)      
 50     ...
 51  
 52 FileField(Field)
 53     allow_empty_file=False     是否允许空文件
 54  
 55 ImageField(FileField)      
 56     ...
 57     注:需要PIL模块,pip3 install Pillow
 58     以上两个字典使用时,需要注意两点:
 59         - form表单中 enctype="multipart/form-data"
 60         - view函数中 obj = MyForm(request.POST, request.FILES)
 61  
 62 URLField(Field)
 63     ...
 64  
 65  
 66 BooleanField(Field)  
 67     ...
 68  
 69 NullBooleanField(BooleanField)
 70     ...
 71  
 72 ChoiceField(Field)
 73     ...
 74     choices=(),                选项,如:choices = ((0,'上海'),(1,'北京'),)
 75     required=True,             是否必填
 76     widget=None,               插件,默认select插件
 77     label=None,                Label内容
 78     initial=None,              初始值
 79     help_text='',              帮助提示
 80  
 81  
 82 ModelChoiceField(ChoiceField)
 83     ...                        django.forms.models.ModelChoiceField
 84     queryset,                  # 查询数据库中的数据
 85     empty_label="---------",   # 默认空显示内容
 86     to_field_name=None,        # HTML中value的值对应的字段
 87     limit_choices_to=None      # ModelForm中对queryset二次筛选
 88      
 89 ModelMultipleChoiceField(ModelChoiceField)
 90     ...                        django.forms.models.ModelMultipleChoiceField
 91  
 92  
 93      
 94 TypedChoiceField(ChoiceField)
 95     coerce = lambda val: val   对选中的值进行一次转换
 96     empty_value= ''            空值的默认值
 97  
 98 MultipleChoiceField(ChoiceField)
 99     ...
100  
101 TypedMultipleChoiceField(MultipleChoiceField)
102     coerce = lambda val: val   对选中的每一个值进行一次转换
103     empty_value= ''            空值的默认值
104  
105 ComboField(Field)
106     fields=()                  使用多个验证,如下:即验证最大长度20,又验证邮箱格式
107                                fields.ComboField(fields=[fields.CharField(max_length=20), fields.EmailField(),])
108  
109 MultiValueField(Field)
110     PS: 抽象类,子类中可以实现聚合多个字典去匹配一个值,要配合MultiWidget使用
111  
112 SplitDateTimeField(MultiValueField)
113     input_date_formats=None,   格式列表:['%Y--%m--%d', '%m%d/%Y', '%m/%d/%y']
114     input_time_formats=None    格式列表:['%H:%M:%S', '%H:%M:%S.%f', '%H:%M']
115  
116 FilePathField(ChoiceField)     文件选项,目录下文件显示在页面中
117     path,                      文件夹路径
118     match=None,                正则匹配
119     recursive=False,           递归下面的文件夹
120     allow_files=True,          允许文件
121     allow_folders=False,       允许文件夹
122     required=True,
123     widget=None,
124     label=None,
125     initial=None,
126     help_text=''
127  
128 GenericIPAddressField
129     protocol='both',           both,ipv4,ipv6支持的IP格式
130     unpack_ipv4=False          解析ipv4地址,如果是::ffff:192.0.2.1时候,可解析为192.0.2.1, PS:protocol必须为both才能启用
131  
132 SlugField(CharField)           数字,字母,下划线,减号(连字符)
133     ...
134  
135 UUIDField(CharField)           uuid类型 UUID是根据MAC以及当前时间等创建的不重复的随机字符串
136     ...
fields-字段

2、Django内置插件:

 1 TextInput(Input)
 2 NumberInput(TextInput)
 3 EmailInput(TextInput)
 4 URLInput(TextInput)
 5 PasswordInput(TextInput)
 6 HiddenInput(TextInput)
 7 Textarea(Widget)
 8 DateInput(DateTimeBaseInput)
 9 DateTimeInput(DateTimeBaseInput)
10 TimeInput(DateTimeBaseInput)
11 CheckboxInput
12 Select
13 NullBooleanSelect
14 SelectMultiple
15 RadioSelect
16 CheckboxSelectMultiple
17 FileInput
18 ClearableFileInput
19 MultipleHiddenInput
20 SplitDateTimeWidget
21 SplitHiddenDateTimeWidget
22 SelectDateWidget
wiegets-插件

2.1、常用的内置插件演示:

 1 # 单radio,值为字符串
 2 # user = fields.CharField(
 3 #     initial=2,
 4 #     widget=widgets.RadioSelect(choices=((1,'上海'),(2,'北京'),))
 5 # )
 6  
 7 # 单radio,值为字符串
 8 # user = fields.ChoiceField(
 9 #     choices=((1, '上海'), (2, '北京'),),
10 #     initial=2,
11 #     widget=widgets.RadioSelect
12 # )
13  
14 # 单select,值为字符串
15 # user = fields.CharField(
16 #     initial=2,
17 #     widget=widgets.Select(choices=((1,'上海'),(2,'北京'),))
18 # )
19  
20 # 单select,值为字符串
21 # user = fields.ChoiceField(
22 #     choices=((1, '上海'), (2, '北京'),),
23 #     initial=2,
24 #     widget=widgets.Select
25 # )
26  
27 # 多选select,值为列表
28 # user = fields.MultipleChoiceField(
29 #     choices=((1,'上海'),(2,'北京'),),
30 #     initial=[1,],
31 #     widget=widgets.SelectMultiple
32 # )
33  
34  
35 # 单checkbox
36 # user = fields.CharField(
37 #     widget=widgets.CheckboxInput()
38 # )
39  
40  
41 # 多选checkbox,值为列表
42 # user = fields.MultipleChoiceField(
43 #     initial=[2, ],
44 #     choices=((1, '上海'), (2, '北京'),),
45 #     widget=widgets.CheckboxSelectMultiple
46 # )
常用内置插件演示

2.2、Form操作动态Select数据:

 1 # forms.py  在app目录下创建forms.py文件,来专门存放form验证的代码
 2 from django.forms import widgets,forms,fields
 3 from app01 import models
 4 
 5 class UserForm(forms.Form):
 6 
 7     name = fields.CharField(
 8         required=False,
 9         widget=widgets.TextInput(attrs={'class':'c1'})
10     )
11 
12     email = fields.EmailField(
13         max_length=12,
14         widget=widgets.TextInput(attrs={"class":"c2"})
15     )
16 
17     user_type = fields.ChoiceField
18         ### 第一种form动态获取select数据
19         #静态变量,仅在程序第一次加载时执行,从数据库读取数据保存至内存,重启服务才能从数据库获取最新数据
20         # choices=models.UserType.objects.values_list('id','type_name'),
21 
22         ### 第二种form动态获取select数据,自定义构造方法,
23         choices=[],
24         widget=widgets.Select
25     )
26 
27     user_type2 = fields.CharField(widget=widgets.Select(choices=[])) #fields['user_type2'].widget.choices
28 
29     def __init__(self,*args,**kwargs):
30         super(UserForm,self).__init__(*args,**kwargs)
31 
32         # 构造方法中实例变量会在每次实例化后执行
33         self.fields["user_type"].choices = models.UserType.objects.values_list('id','type_name')
34         self.fields['user_type2'].widget.choices = models.UserType.objects.values_list('id','type_name')
35 
36 
37 
38 # view.py  在view.py视图函数中去调用From验证
39 
40 from django.shortcuts import render
41 from app01 import models
42 
43 def index(request):
44     from app01.forms import UserForm
45     ### 第一种form动态获取select数据
46     #obj = UserForm() # 实例化UserForm类
47     # obj.fields["user_type"].choices=models.UserType.objects.values_list('id','type_name') #每次刷新web页面就相当于实例化一次UserForm类,从而从数据库获取最新数据
48 
49     ### 第二种form动态获取select数据,自定义构造方法
50     obj = UserForm() #实例化UserForm类,这里只需要实例化,而form UserForm类中重写的构造方法中的实例变量会在每次实例化之后执行一次
51     return render(request,'index.html',{'obj':obj})
52 
53 
54 
55 #HTML
56 <body>
57     <p>{{ obj.name }}</p>
58     <p>{{ obj.email }}</p>
59     <p>{{ obj.user_type }}</p>
60     <p>{{ obj.user_type2 }}</p>
61 </body>
方式一,自定义构造方法
 1 ##form.py
 2 #ModelChoiceField具体字段如下:
 3 ModelChoiceField(ChoiceField)
 4     ...                        django.forms.models.ModelChoiceField
 5     queryset,                  # 查询数据库中的数据
 6     empty_label="---------",   # 默认空显示内容
 7     to_field_name=None,        # HTML中value的值对应的字段
 8     limit_choices_to=None      # ModelForm中对queryset二次筛选 ###
 9 
10 
11 
12 from django.forms import widgets,forms,fields
13 from django.forms.models import ModelChoiceField  #django自己帮我们提供的
14 
15 class UserForm(forms.Form):
16         user_type3 = ModelChoiceField(
17         queryset=models.UserType.objects.all(),
18         to_field_name="id",   #html中的value的值的对应字段,一般情况下只用id
19         empty_label="请选择用户类型",  #默认空显示内容
20         )
21 
22 
23 ##ModelChoiceField必须跟model中的__str__函数想结合使用:
24 class UserType(models.Model):
25     type_name = models.CharField(max_length=32)
26 
27     def __str__(self):  #必须跟__str__这个函数结合使用
28         return self.type_name
29 
30 
31 
32 
33 
34 #view.py
35 
36 def index(request):
37 
38     from app01.forms import UserForm
39     obj = UserForm()
40 
41     return render(request,'index.html',{'obj':obj})
42 
43 
44 #HTML
45 <body>
46     <p>{{ obj.user_type3 }}</p>
47 </body>
方式二、ModelChoiceField

3、Form内置钩子进行验证:

django form中还预留了钩子,主要有三个类型的钩子:_clean_fields (单个字段验证,,如:登录页面user or password字段)、_clean_fields (整体验证,如:登录页面整体)、_post_clean(预留的钩子,主要坐收尾工作)

3.1、_clean_fields 

 1 from app01 import models
 2 from django.core.exceptions import ValidationError  #源码里面抛出的异常
 3 class RegisterForm(forms.Form):
 4     user = fields.CharField()   #下面的方法要想执行,先通过这边正则验证
 5     email = fields.EmailField()
 6      #根据源码,我们知道在我们自己自定义的form中,是 定义clean_字段名 方法,去验证,然后赋值给 cleaned_data
 7     #clean_%s 这个函数必须要有返回值,赋值给self.cleaned_data['%s']
 8     def clean_user(self):
 9         #注册的时候,如果存在此用户,则报错,没有,则继续执行
10         c = models.User.objects.filter(name=self.cleaned_data['user'].count())
11         if not c:
12             return self.cleaned_data['user']
13         else:
14             raise ValidationError('用户名已经存在',code="xxxx")  #存在就包异常
15  
16  
17     def clean_email(self):
18  
19         return self.cleaned_data['email']  #这边必须返回一个值
clean_fields 单个字段验证

3.2、_clean_form 

 1 from app01 import models
 2 from django.core.exceptions import ValidationError  #源码里面抛出的异常
 3 class RegisterForm(forms.Form):
 4     user = fields.CharField()   #下面的方法要想执行,先通过这边正则验证
 5     pwd = fields.CharField()
 6  
 7  
 8     def clean(self):
 9         c = models.User.objects.filter(name=self.cleaned_data['user'],pwd=self.cleaned_data['pwd']).count()
10         if not c:
11             return self.cleaned_data  #这边必须有一个返回值,因为源码里面有返回值
12         else:
13             raise ValidationError("用户名或密码错误",code="xxxxx")  #这个异常应该给整体,不应该给某一个字段
clean_form from整体验证

3.3、单个字段错误提示和form整体错误提示

1 obj.errors:
2         {
3             #self._clean_form() 返回的错误信息,也就是整体返回的错误信息,有的地方写成: NON_FIFLD_ERRORS:[],其实就是代指的__all__
4             '__all__':[],
5             # clean_user和clean_pwd返回的错误信息,就是单个验证返回的错误信息
6             'user':[{'code':"required",'message':'xxxx'}],
7             'pwd':[{'code':"required",'message':'xxxx'}]
8         }
错误提示定义

4、自定义验证规则:

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开头')],
    )
方式一
import re
from django.forms import Form
from django.forms import widgets
from django.forms import fields
from django.core.exceptions import ValidationError
 
 
# 自定义验证规则
def mobile_validate(value):
    mobile_re = re.compile(r'^(13[0-9]|15[012356789]|17[678]|18[0-9]|14[57])[0-9]{8}$')
    if not mobile_re.match(value):
        raise ValidationError('手机号码格式错误')
 
 
class PublishForm(Form):
 
 
    title = fields.CharField(max_length=20,
                            min_length=5,
                            error_messages={'required': '标题不能为空',
                                            'min_length': '标题最少为5个字符',
                                            'max_length': '标题最多为20个字符'},
                            widget=widgets.TextInput(attrs={'class': "form-control",
                                                          'placeholder': '标题5-20个字符'}))
 
 
    # 使用自定义验证规则
    phone = fields.CharField(validators=[mobile_validate, ],
                            error_messages={'required': '手机不能为空'},
                            widget=widgets.TextInput(attrs={'class': "form-control",
                                                          'placeholder': u'手机号码'}))
 
    email = fields.EmailField(required=False,
                            error_messages={'required': u'邮箱不能为空','invalid': u'邮箱格式错误'},
                            widget=widgets.TextInput(attrs={'class': "form-control", 'placeholder': u'邮箱'}))
方式二
# 自定义方法
from django import forms
    from django.forms import fields
    from django.forms import widgets
    from django.core.exceptions import ValidationError
    from django.core.validators import RegexValidator
 
    class FInfo(forms.Form):
        username = fields.CharField(max_length=5,
                                    validators=[RegexValidator(r'^[0-9]+$', 'Enter a valid extension.', 'invalid')], )
        email = fields.EmailField()
 
        def clean_username(self):
            """
            Form中字段中定义的格式匹配完之后,执行此方法进行验证
            :return:
            """
            value = self.cleaned_data['username']
            if "666" in value:
                raise ValidationError('666已经被玩烂了...', 'invalid')
            return value
方式三
#同时生成多个标签进行验证
from django.forms import Form
from django.forms import widgets
from django.forms import fields
 
from django.core.validators import RegexValidator
 
 
############## 自定义字段 ##############
class PhoneField(fields.MultiValueField):
    def __init__(self, *args, **kwargs):
        # Define one message for all fields.
        error_messages = {
            'incomplete': 'Enter a country calling code and a phone number.',
        }
        # Or define a different message for each field.
        f = (
            fields.CharField(
                error_messages={'incomplete': 'Enter a country calling code.'},
                validators=[
                    RegexValidator(r'^[0-9]+$', 'Enter a valid country calling code.'),
                ],
            ),
            fields.CharField(
                error_messages={'incomplete': 'Enter a phone number.'},
                validators=[RegexValidator(r'^[0-9]+$', 'Enter a valid phone number.')],
            ),
            fields.CharField(
                validators=[RegexValidator(r'^[0-9]+$', 'Enter a valid extension.')],
                required=False,
            ),
        )
        super(PhoneField, self).__init__(error_messages=error_messages, fields=f, require_all_fields=False, *args,
                                         **kwargs)
 
    def compress(self, data_list):
        """
        当用户验证都通过后,该值返回给用户
        :param data_list:
        :return:
        """
        return data_list
 
############## 自定义插件 ##############
class SplitPhoneWidget(widgets.MultiWidget):
    def __init__(self):
        ws = (
            widgets.TextInput(),
            widgets.TextInput(),
            widgets.TextInput(),
        )
        super(SplitPhoneWidget, self).__init__(ws)
 
    def decompress(self, value):
        """
        处理初始值,当初始值initial不是列表时,调用该方法
        :param value:
        :return:
        """
        if value:
            return value.split(',')
        return [None, None, None]
方式四

5、Form内置序列化错误信息:

  1 #form.py
  2 rom django import forms
  3 from django.forms import fields,widgets
  4 
  5 class LoginForm(forms.Form):
  6     username = fields.CharField() #这跟login.html中的input标签的name属性的值一致
  7     password = fields.CharField(
  8         max_length=64,
  9         min_length=12
 10     )
 11 
 12 
 13 
 14 
 15 
 16 
 17 #view 中的login 函数
 18 #第一种 使用ErrorDict中的as_json函数,不过在HTML中相应获取错误信息需要反解两次
 19 from django.shortcuts import render,HttpResponse
 20 import json
 21 def login(request):
 22     ret = {'status':True,'error':None,'data':None}
 23     if request.method == "GET":
 24         return render(request,'login.html')
 25     elif request.method == "POST":
 26         obj = LoginForm(request.POST)
 27         if obj.is_valid():
 28             print(obj.cleaned_data)
 29         else:
 30             # print(type(obj.errors)) 通过打印类型得知是属于ErrorDict
 31             from django.forms.utils import ErrorDict  #通过源码得知:as_data 返回的是原生的字典,as_json()是类似json格式的字符串
 32             ret['error'] = obj.errors.as_json()
 33         return HttpResponse(json.dumps(ret))  #因为as_json()和json.dumps 相当于序列化了两次
 34 
 35 
 36 
 37 #第二张自定义JsonCustomEncoder类
 38 from django.core.exceptions import ValidationError
 39 import json
 40 class JsonCustomEncoder(json.JSONEncoder):  #直接在cls=JsonCustomEncoder类名,去序列化复杂的数据类型
 41     def default(self,field):
 42         if isinstance(field,ValidationError):  #
 43             # # from django.core.exceptions import ValidationError  #看一下这个异常,发现field的字段和错误信息都保存在这个ValidationError对象里
 44             return {'code':field.code,'messages':field.messages}
 45         else:
 46             return json.JSONEncoder.default(self,field)
 47 
 48 
 49 
 50 from django.shortcuts import render,HttpResponse
 51 import json
 52 
 53 def login(request):
 54     ret = {'status':True,'error':None,'data':None}
 55     if request.method == "GET":
 56         return render(request,'login.html')
 57     elif request.method == "POST":
 58         obj = LoginForm(request.POST)
 59         if obj.is_valid():
 60             print(obj.cleaned_data)
 61         else:
 62             ret['error'] = obj.errors.as_data()
 63             # for k,v in obj.errors.as_data().items():
 64             #     print(k,v)    通过打印发现as_data后 value是一个ValidationError对象
 65             # ret = {'k1':'v1','k2':ValueError()}  #像这种复杂数据类型,json是不能序列化的,我们只能做局部处理
 66 #这边cls 是序列化的时候,对每一个字段序列化的时候,都会调用一个它的default方法,因此重写JsonCustomEncoder类中default方法来进行复杂情况下的序列化操作
 67         result = json.dumps(ret,cls=JsonCustomEncoder)
 68         return HttpResponse(result)
 69 
 70 
 71 
 72 
 73 #HTML
 74 """
 75 <body>
 76     <form id="fm">
 77         {% csrf_token %}
 78         <p><input type="text" name="username" /></p>  #这边username 需要跟 from 里面的字段 是一模一样
 79         <p><input type="text" name="password" /></p>
 80         <a id="submit">提交</a>
 81     </form>
 82 
 83     <script src="/static/jquery-1.12.4.js"></script>
 84     <script>
 85         $(function(){
 86             $('#submit').click(function(){
 87                 $.ajax({
 88                     url:'/login/',
 89                     type:'post',
 90                     data:$('#fm').serialize(),
 91                     sucess:function(arg){
 92                         //console.log(arg);
 93                         arg = JSON.parse(arg);
 94                         console.log(arg)
 95                     },
 96                     error:function(){
 97 
 98                     }
 99                 })
100             })
101         })
102     </script>
103 </body>"""
104 
105 
106 
107 
108 #返回的数据类型为:  
109 
110 "{\"data\": null, \"status\": true, \"error\": {\"username\": [{\"code\": \"required\", \"messages\": [\"This field is required.\"]}],
111  \"password\": [{\"code\": \"required\", \"messages\": [\"This field is required.\"]}]}}"
序列化错误信息的两种方式

6、Form类中的fields、widgets 简单示例:

a、Form类:

from django import forms  # 导入forms
from django.forms import widgets  # 导入插件
from django.forms import fields   # 导入字段,以后对于像charField、EmailField等字段格式的处理不需要在通过form.进行定义了,而是通过fields进行定义

class FM(forms.Form):
    # 字段本身只做验证
    user = fields.CharField(
        error_messages={'required': '用户名不能为空.'},  # 定义错误信息的提示语,required为定义输入框为空的提示语
        # widget=widgets.Textarea(attrs={'class': 'c1'}),  # 导入插件中的多行文本输入,并定义样式
        label="用户名",  # 定义标签名称
        )
    pwd = fields.CharField(
        max_length=12,  # 定义字符最大、最近小字符长度,及相应错误提示语
        min_length=6,
        error_messages={'required': '密码不能为空.', 'min_length': '密码长度不能小于6', "max_length": '密码长度不能大于12'},
        widget=widgets.PasswordInput(attrs={'class': 'c2'})  # 导入插件中的密码非明文输入,并定义样式
    )
    email = fields.EmailField(error_messages={'required': '邮箱不能为空.', 'invalid': "邮箱格式错误"})  # invalid定义输入框无效是的提示语

    f = fields.FileField()  # 文件上传

    p = fields.FilePathField(path='app01')  # 将路径下的全部文件进行展示

    city1 = fields.ChoiceField(  # 单项选择框
        choices=[(0, '上海'), (1, '广州'), (2, '东莞')]
    )                                                                   
    city2 = fields.MultipleChoiceField(      # 多项选择框
        choices=[(0, '上海'), (1, '广州'), (2, '东莞')]
    )

b.views:

from app01 import models


def fm(request):
    if request.method == "GET":
        # 从数据库中吧数据获取到
        dic = {
            "user": 'r1',
            'pwd': 'password',
            'email': 'email@163.com',
            'city1': 1,
            'city2': [1, 2]
        }
        obj = FM(initial=dic)  # 初始化操作,通过字典形式传递默认值
        return render(request, 'fm.html', {'obj': obj})
    elif request.method == "POST":
        obj = FM(request.POST)
        r1 = obj.is_valid()
        if r1:
            # obj.cleaned_data
            print(obj.changed_data)
            # models.UserInf.objects.create(**obj.cleaned_data)
        else:
            # errors 继承了ErrorDict类
            print(obj.errors.as_json())
            # print(obj.errors['user'][0])
            return render(request, 'fm.html', {'obj': obj})
    return redirect('http://www.ww.qq.com')

c、HTML:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
    <form action="/fm/" method="POST">
        {% csrf_token %}
        <p>{{ obj.user.label}}{{ obj.user }} {{ obj.errors.user.0 }}</p>  <!-- 类似于view视图中的 obj.errors['user'][0]-->
        <p>{{ obj.pwd }} {{ obj.errors.pwd.0 }}</p>
        <p>{{ obj.email }}{{ obj.errors.email.0 }}</p>
        <p>{{ obj.f}}</p>
        <p>{{ obj.p}}</p>
        <p>{{ obj.city1}}</p>
        <p>{{ obj.city2}}</p>
        <input type="submit" value="提交" />
    </form>
</body>
</html>
posted @ 2018-04-30 11:50  Wilson_Blogs  阅读(288)  评论(0编辑  收藏  举报