• django学习之- Form


    参考:http://www.cnblogs.com/wupeiqi/articles/6144178.html
    FORM中的字段只对post上来的数据进行form验证,
    主要涉及:字段 和 插件
    字段:对用户请求数据的验证。
    插件:用于自动生成html。
    - 自定义:
    - 创建类
    - 定义字段(验证)
    - 插件(生成html)
    - 初始化操作
    实例:通过前端html和后台django,通过from实现一个简单的表单验证及多个功能的展示
    前端fm.html代码:
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    {#功能:实现表单进行数据验证,并在验证未通过情况下,页面不进行刷新,只提示错误#}
    <form action="/fm" method="post">
        {% csrf_token %}
    {#    以下第一个user.label为FM表单user字段的label值,第二个obj.user为FM表单的user字段,最后的一个是FM表单的error_messages错误提醒#}
        {% csrf_token %}
        <p>
            {{ obj.user.label }}{{ obj.user }}{{ obj.errors.user.0 }}
        </p>
        <p>
            {{ obj.pwd.label }}{{ obj.pwd }}{{obj.errors.pwd.0 }}
        </p>
        <p>
            {{ obj.email.label }}{{ obj.email }}{{ obj.errors.email.0 }}
        </p>
        <p>
            {{ obj.f.label }}{{ obj.f }}{{ obj.errors.f.0 }}
        </p>
        <p>
    {#        这个提交的是选中的文件的路径#}
            {{ obj.p }}
        </p>
        <p>
    {#        choice下拉框选项#}
            {{ obj.cite }}
        </p>
        <p>
    {#        单选#}
            {{ obj.cite2 }}
        </p>
        <p>
            {{ obj.mcite }}
        </p>
        <input type="submit" value="提交" />
    </form>
    </body>
    </html>
    View Code

      后台代码

    from django import forms
    from django.forms import fields
    # widgets 插件可以定义html的标签和样式,fields表示字段
    from django.forms import widgets
    class FM(forms.Form):
        # 这里的各个字段,本身自己只做验证
        user = fields.CharField(
            error_messages={'required':'用户名不能为空'}, # 错误提醒
            widget = widgets.Textarea(attrs={'class':'c1','style':'background:#e2e3e4'}), # html标签和样式
            label = '用户名', # 标签
            #initial='admin',  # 定义初始值
            )
        pwd = fields.CharField(
            max_length=12,
            min_length=6,
            error_messages={'required':'密码不能为空','min_length':'密码最小长度6位','max_length':'密码最大长度为12位'},
            widget = widgets.PasswordInput(attrs={'style':'background:#e3e4e5'}),
            label = '密码',
        )
        email = fields.EmailField(
            error_messages={'required':'邮箱不可以为空','invalid':'邮箱格式不正确'},
            label = '邮箱',
        )
        f = fields.FileField(
            label='上传文件'
        )
        # 可以显示指定目录下所有的文件
        p = fields.FilePathField(
            path='d:/'
        )
        # 下拉框
        cite = fields.ChoiceField(
            choices=[(0,'bj'),(1,'sh'),(2,'sz')]
        )
        cite2 = fields.CharField(
        initial=2,
        widget=widgets.RadioSelect(choices=((0,'man'),(1,'girl')))
        )
        # 多选下拉框
        mcite = fields.MultipleChoiceField(
            choices=[(0,'bj'),(1,'sh'),(2,'sz')]
        )
    
    def fm(request):
        # GET将返回表单输入框
        if request.method == 'GET':
            # 从数据库提取数据,为字段生成默认值,注意必须为字典格式,健必须为FM的字段名
            dic = {
                'user':'r1',
                'pwd':'abc',
                'email':'test@test',
                'cite':1,
                'mcite':[1,2],
            }
            obj = FM(initial=dic) # 这里将dic作为参数传入,即可生成默认值
            return render(request,'fm.html',{'obj':obj})
        if request.method == 'POST':
            # POST获取所有提交的数据并进行校验(is_valid),cleaned_data以字典格式返回所有校验成功的数据,errors返回所有校验失败的数据,
            # 直接将obj返回给前端,前端进行错误打印,as_json以json格式打印所有错误
            obj = FM(request.POST)
            ck = obj.is_valid()
            if ck:
                print(obj.cleaned_data)
                # 将表单数据进行数据库添加
                models.UserName.objects.create(**obj.cleaned_data)
                return redirect('/fm')
            else:
                print(obj.errors)
                print(obj.errors.as_json())
                return render(request,'fm.html',{'obj':obj})
    View Code
    Form内置字段:
    ### 字符串验证###
    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, 小数位长度
    ### 时间格式验证###3
    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
    ...
    ### 这个就相当于 CharField + validators ####
    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)  # URL的正则表达式
    ...
    BooleanField(Field) # 布尔
    ...
    NullBooleanField(BooleanField)
    ...
    ### 比较重要######
    ChoiceField(Field) # 单选下拉框
    ...
    choices=(), 选项,如:choices = ((0,'上海'),(1,'北京'),)
    required=True, 是否必填
    widget=None, 插件,默认select插件
    label=None, Label内容
    initial=None, 初始值
    help_text='', 帮助提示
    MultipleChoiceField(ChoiceField) # 多选下拉框
    ...

    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= '' 空值的默认值



    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类型
    ##### 内置插件 ######
    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
    每个插件内部都可以使用attr自定制属性
    实例:通过表单实现单选
    forms.py 内容
    from django.forms import widgets,fields
    from django import forms
    from app01 import models
    from django.forms.models import ModelChoiceField,ModelMultipleChoiceField
    # ModelChoiceField 单选
    # ModelMultipleChoiceField 多选
    class UserInfoForm(forms.Form):
        user = fields.CharField(
            required=False,
            widget = widgets.Textarea(attrs={'class':'c1'})
        )
        pwd = fields.CharField(
            max_length=12,
            widget = widgets.PasswordInput(attrs={'class':'c1'})
        )
        user_type = fields.ChoiceField(
            # choices=[(0,'普通用户'),(1,'超级用户')],
            choices=[],
            widget=widgets.Select
        )
        user_type2 = fields.CharField(
            widget=widgets.Select(choices=[])
        )
        user_type3 = ModelChoiceField(
            empty_label='请选择用户类型',
            # 使用此方法虽然不用使用构造方法,但是表需要定制__str__方法
            queryset=models.UserType.objects.all(),
            to_field_name='id'  # 生成select标签内option的value值
        )
        def __init__(self,*args,**kwargs):
            super(UserInfoForm,self).__init__(*args,**kwargs)
            self.fields['user_type'].choices = models.UserType.objects.values_list('id','name')
            self.fields['user_type2'].widget.choices = models.UserType.objects.values_list('id','name')
    View Code
    views.py内容
    def index2(request):
        from app01.forms import UserInfoForm
        obj = UserInfoForm()
        return render(request,'indexform.html',{'obj':obj})
    indexform.html内容
    <body>
    <p>{{ obj.user }}</p>
    <p>{{ obj.pwd }}</p>
    <p>{{ obj.user_type }}</p>
    <p>{{ obj.user_type2 }}</p>
    <p>{{ obj.user_type3 }}</p>
    </body>

    form: 数据验证,经历3个阶段

        - 每一个字段(正则,字段钩子)
    - clean
    - _post_clean
    对于错误信息:整体的错误信息放于__all__内。
    实例:数据验证,使用钩子
    forms.py内容
    # 钩子举例,注册,登录
    from django.core.exceptions import ValidationError
    class RegisterForm(forms.Form):
        '''字段增加验证方式,首先进行user字段的正则表达式验证,如果通过了。然后进行源码里预留的钩子clean_user验证'''
        user = fields.CharField()
        email = fields.EmailField()
    
        def clean_user(self):
            '''源码里通过钩子clean+_field,增加正则表达式验证'''
            c = models.User.objects.filter(name=self.cleaned_data['user']).count()
            if not c:
                return self.cleaned_data['user']
            else:
                raise ValidationError('用户名已经存在',code='xxx')
        def clean_email(self):
            pass
    
    class LoginForm(forms.Form):
        user = fields.CharField()
        pwd = fields.CharField(validators=[])  # 这个参数可以自定义正则表达式验证
    
        def clean_user(self):
            '''第一类钩子字段验证,源码里通过钩子clean+_field,增加正则表达式验证'''
            c = models.User.objects.filter(name=self.cleaned_data['user']).count()
            if not c:
                return self.cleaned_data['user']
            else:
                raise ValidationError('用户名已经存在',code='xxx')
        def clean_pwd(self):
            pass
        def clean(self):
            '''第二类钩子 整体进行验证'''
            self.cleaned_data['user']
            self.cleaned_data['pwd']
            c = models.User.objects.filter(name=self.cleaned_data['user'],pwd=self.cleaned_data['pwd']).count()
            if c:
                return self.cleaned_data
            else:
                raise ValidationError('用户名或密码错误')
        def _post_clean(self):
            '''第三类钩子'''
            pass
    View Code

    views.py 内容

     def register(request):
        from app01.forms import RegisterForm
        obj = RegisterForm(request.POST)
        if obj.is_valid():
            obj.cleaned_data
        else:
            obj.errors
     

























  • 相关阅读:
    查看mysql版本的四种方法及常用命令
    newInstance和new的区别(good)
    Citrix 服务器虚拟化之六 Xenserver虚拟机创建与快照
    Java实现 蓝桥杯 算法训练 排序
    Java实现 蓝桥杯 算法训练 排序
    Java实现 蓝桥杯 算法训练 排序
    Java实现 蓝桥杯 算法训练 2的次幂表示
    Java实现 蓝桥杯 算法训练 2的次幂表示
    Java实现 蓝桥杯 算法训练 前缀表达式
    Java实现 蓝桥杯 算法训练 前缀表达式
  • 原文地址:https://www.cnblogs.com/zy6103/p/8030376.html
Copyright © 2020-2023  润新知