• Django——form表单验证(创建,内置字段,自定义异常,form表单的前端数据实时更新)


    Form表单验证

     1、创建Form类

     1 from django.forms import Form
     2 from django.forms import widgets
     3 from django.forms import fields
     4 
     5 class FM(Form):
     6     user = fields.CharField(
     7         error_messages={'required':'用户名不能为空'}
     8     )
     9     pwd = fields.CharField(
    10         max_length=18,
    11         min_length=9,
    12         error_messages={'required':'密码不能为空','max_length':'密码长度不能大于12','min_length':'密码长度不能小于6'},
    13         widget=widgets.PasswordInput(attrs={'class':'c1','id':'i1'})
    14     )
    15     email = fields.EmailField(
    16         error_messages={'required': '邮箱不能为空.', 'invalid': "邮箱格式错误"}
    17     )
    18     gender = fields.ChoiceField(
    19         choices=((1,''),(2,''),),
    20         initial = 2,     #默认值
    21         # widget=widgets.Select
    22         widget=widgets.RadioSelect
    23     )
    24     city = fields.CharField(
    25         initial=2,
    26         widget=widgets.Select(choices=((1,'上海'),(2,'北京'),))
    27     )
    28     abc = fields.MultipleChoiceField(
    29         choices=((1,'a'),(2,'b'),(3,'c'),(4,'d')),
    30         initial=[1,2],
    31         widget = widgets.CheckboxSelectMultiple
    32     )
    View Code

    2、views函数处理

     1 def form(request):
     2     if request.method == 'GET':
     3         obj = FM()
     4         return render(request,'form.html',{'obj':obj})
     5     elif request.method == 'POST':
     6         obj = FM(request.POST)
     7         if obj.is_valid():
     8             values = obj.clean()
     9             print(values)
    10         else:
    11             errors = obj.errors
    12             print(errors)
    13         return render(request,'form.html',{'obj':obj})
    View Code

    3、html页面

     1 <!DOCTYPE html>
     2 <html lang="en">
     3 <head>
     4     <meta charset="UTF-8">
     5     <title>Title</title>
     6 </head>
     7 <body>
     8     <form method="post" action="#">
     9         {% csrf_token %}
    10         <p>{{ obj.user }}{{ obj.user.errors.0 }}</p>
    11         <p>{{ obj.pwd }}{{ obj.pwd.errors.0 }}</p>
    12         <p>{{ obj.email }}{{ obj.email.errors.0 }}</p>
    13         <p>{{ obj.city }}{{ obj.city.errors.0 }}</p>
    14         <p>{{ obj.gender }}{{ obj.gender.errors.0 }}</p>
    15         <p>{{ obj.abc }}{{ obj.abc.errors.0 }}</p>
    16         <input type="submit" value="提交">
    17     </form>
    18 </body>
    19 </html>
    View Code

    Form内置字段

    内置字段 --> username = field.CharField(里面写方法)

    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,              最小值
     
    FloatField(IntegerField)
        ...
     
    DecimalField(IntegerField)
        max_value=None,              最大值
        min_value=None,              最小值
        max_digits=None,             总长度
        decimal_places=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)
        ...
     
     
    BooleanField(Field)  
        ...
     
    NullBooleanField(BooleanField)
        ...
     
    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二次筛选
         
    ModelMultipleChoiceField(ModelChoiceField)
        ...                        django.forms.models.ModelMultipleChoiceField
     
     
         
    TypedChoiceField(ChoiceField)
        coerce = lambda val: val   对选中的值进行一次转换
        empty_value= ''            空值的默认值
     
    MultipleChoiceField(ChoiceField)
        ...
     
    TypedMultipleChoiceField(MultipleChoiceField)
        coerce = lambda val: val   对选中的每一个值进行一次转换
        empty_value= ''            空值的默认值
     
    ComboField(Field)
        fields=()                  使用多个验证,如下:即验证最大长度20,又验证邮箱格式
                                   fields.ComboField(fields=[fields.CharField(max_length=20), fields.EmailField(),])
     
    MultiValueField(Field)
        PS: 抽象类,子类中可以实现聚合多个字典去匹配一个值,要配合MultiWidget使用
     
    SplitDateTimeField(MultiValueField)
        input_date_formats=None,   格式列表:['%Y--%m--%d', '%m%d/%Y', '%m/%d/%y']
        input_time_formats=None    格式列表:['%H:%M:%S', '%H:%M:%S.%f', '%H:%M']
     
    FilePathField(ChoiceField)     文件选项,目录下文件显示在页面中
        path,                      文件夹路径
        match=None,                正则匹配
        recursive=False,           递归下面的文件夹
        allow_files=True,          允许文件
        allow_folders=False,       允许文件夹
        required=True,
        widget=None,
        label=None,
        initial=None,
        help_text=''
     
    GenericIPAddressField
        protocol='both',           both,ipv4,ipv6支持的IP格式
        unpack_ipv4=False          解析ipv4地址,如果是::ffff:192.0.2.1时候,可解析为192.0.2.1, PS:protocol必须为both才能启用
     
    SlugField(CharField)           数字,字母,下划线,减号(连字符)
        ...
     
    UUIDField(CharField)           uuid类型
        ...  

    内置插件

     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
    View Code

    常用选择插件

    # 单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
    # )
    

    初始化数据(编辑时,显示之前的数据)

    views端:

    class FM(Form):
         form类
         ...
       
    
    
    from app01 import models
    def fm(request):
        if request.method == "GET":
            # 从数据库中吧数据获取到
            dic = {
                "user": 'r1',
                'pwd': '123123',
                'email': 'sdfsd',
                '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
                models.UserInf.objects.create(**obj.cleaned_data)
            else:
                # ErrorDict
                # print(obj.errors.as_json())
                # print(obj.errors['user'][0])
                return render(request,'fm.html', {'obj': obj})
            return render(request,'fm.html')

    html端

    1 <form method="POST" enctype="multipart/form-data">
    2     {% csrf_token %}
    3     <p>{{ form.user }} {{ form.user.errors }}</p>
    4     <p>{{ form.city }} {{ form.city.errors }}</p>
    5  
    6     <input type="submit"/>
    7 </form>
    View Code

    自定义异常

    a.clean_%s(self)  #clean_ + 要审查的那个字段

    源代码:

    实现

    b._post_clean(self)  # 重写clean方法

    源代码

    实现

    c.clean(self)  # 重写clean方法

    源代码

    实现

     1 views.py
     2 
     3 from django.shortcuts import render,redirect,HttpResponse
     4 
     5 from cmdb import models
     6 from django import forms
     7 from django.forms import fields
     8 from django.core.exceptions import ValidationError
     9 
    10 class UserForm(forms.Form):
    11     username = fields.CharField(label='用户名')
    12     email = fields.EmailField(label='email')
    13 
    14     user_type = fields.ChoiceField(choices=models.UserType.objects.values_list('id', 'name'))
    15 
    16     def clean_username(self):
    17         # 自定义错误验证-->验证单个
    18         value = self.cleaned_data['username']
    19         if value == 'root':
    20             return value
    21         else:
    22             raise ValidationError('用户名输入错误')
    23 
    24     def _post_clean(self):
    25         # 自定义错误验证-->验证多个
    26         v1 = value = self.cleaned_data['username']
    27         v2 = value = self.cleaned_data['email']
    28         if v1 == 'root' and v2 == 'alex@163.com':
    29             pass
    30         else:
    31             self.add_error('__all__',ValidationError('用户名或邮箱输入错误'))
    32 
    33     def clean(self):
    34         v1 = value = self.cleaned_data['username']
    35         v2 = value = self.cleaned_data['email']
    36         if v1 == 'root' and v2 == 'alex@163.com':
    37             pass
    38         else:
    39             raise ValidationError('用户名或邮箱输入错误')
    40 
    41 
    42 
    43 def index(request):
    44     if request.method == 'GET':
    45         obj = UserForm()
    46         return render(request,'index.html',{'obj':obj})
    47     elif request.method == 'POST':
    48         obj = UserForm(request.POST)
    49         print(obj.is_valid())
    50         # print(obj.clean())
    51         print(obj.cleaned_data)
    52         print(obj.errors)
    53         return render(request, 'index.html', {'obj': obj})
    54 
    55 
    56 index.html
    57 
    58 <!DOCTYPE html>
    59 <html lang="en">
    60 <head>
    61     <meta charset="UTF-8">
    62     <title>Title</title>
    63 </head>
    64 <body>
    65     <form action="/index/" method="post">
    66         {% csrf_token %}
    67         {{ obj.as_p }}
    68         <input type="submit" value="提交" />
    69     </form>
    70 </body>
    71 </html>
    View Code

    保持发送到前端的数据实时更新  # {{ obj.as_p }}   {{ obj.name }}  {{ obj.name.errors.0 }}

    方法一:重写构造函数

     1 from django import forms
     2 from django.forms import fields
     3 
     4 class UserForm(forms.Form):
     5     username = fields.CharField(label='用户名')
     6     email = fields.EmailField(label='email')
     7 
     8     user_type1 = fields.ChoiceField(choices=models.UserType.objects.values_list('id', 'name'))
     9 
    10     def __init__(self,*args,**kwargs):
    11         super(UserForm,self).__init__(*args,**kwargs)
    12         self.fields['user_type1'].widget.choices = models.UserType.objects.all().values_list('id', 'name')
    View Code

    方法二:使用ModelChoiceField  # 要在要调用的model写上def__str__:self.xxx

    里面可以加的参数

     1 class UserForm(forms.Form):
     2     username = fields.CharField(label='用户名')
     3     email = fields.EmailField(label='email')
     4 
     5     from django.forms import models as models_fields
     6 
     7     user_type2 = models_fields.ModelChoiceField(queryset=models.UserType.objects.all(),
     8                                                 empty_label='请选择用户类型',
     9                                                 to_field_name="id",
    10                                                 limit_choices_to={'id': 1})
    View Code

  • 相关阅读:
    git 相关
    3D渲染相关基本概念
    c#调用GDAL判断图片文件是否损坏
    8.26 轩然大波
    宽容与未来
    vue学习:打开/刷新一个页面时,触发一个后端请求
    linux histroy显示时间
    从数的角度理解视角转换
    对非法网站的一次提权
    简单的BC站点getshell
  • 原文地址:https://www.cnblogs.com/x54256/p/8310485.html
Copyright © 2020-2023  润新知