• python之路(20)django之Form组件


    前言

      Form组件的几大作用

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

    目录


     Form组件的创建

    views

    from django.shortcuts import render,HttpResponse,redirect
    from django import forms
    from django.forms import fields
    
    
    class F1Form(forms.Form):
        # 不能为空,长度6-18
        user = fields.CharField(
            max_length=18,
            min_length=6,
            required=True,
            #自定义错误的提示
            error_messages={'required': '用户名不能为空','max_length': '太长了','min_length': '太短了','invalid':'..'}
        )
        # 不能为空,长度32
        pwd = fields.CharField(required=True,min_length=32)
        # 不能为空,邮箱格式
        age = fields.IntegerField(
            required=True,
            error_messages={'required':'年龄不能为空', 'invalid':'必须为数字'}
        )
        # 不能为空,数字格式
        email = fields.EmailField(
            required=True,
            min_length=8,
            error_messages={'required':'邮箱不能为空', 'invalid':'邮箱格式错误'}
        )
    
    
    
    
    def f1(request):
        if request.method == "GET":
            obj = F1Form()
            return  render(request,'f1.html',{'obj':obj})
        else:
            # u = request.POST.get('user') #不能为空,长度6-18
            # p = request.POST.get('pwd') #不能为空,长度32
            # e = request.POST.get('email') #不能为空,邮箱格式
            # a = request.POST.get('age') #不能为空,数字格式
            # print(u,p,e,a)
    
            # 检查是否为空
            # 检查格式是否正确
            obj = F1Form(request.POST)
            # 用户是否验证成功
            if obj.is_valid():
                #用户提交的数据
                print('验证成功',obj.cleaned_data)
                #验证失败返回<ul class="errorlist"><li>user<ul class="errorlist">
                # <li>Ensure this value has at least 6 characters (it has 4).</li></ul></li></ul>
                return redirect('http://www.baidu.com')
            else:
                #显示错误信息
                print('验证失败',obj.errors)
                #验证成功返回字典 {'user': '121212', 'pwd': '11111111111111111111111111111111', 'age': 12, 'email': '11111111@qq.com'}
                return  render(request,'f1.html',{'obj':obj})
    
            return  HttpResponse('OK')

    html

        <form id="fm" action="/f1.html" method="POST" novalidate>
            <!--
            <P><input type="text" name="user"/>{{ obj.errors.user.0 }}</P>
            <P><input type="text" name="pwd"/>{{ obj.errors.pwd.0 }}</P>
            <P><input type="text" name="age"/>{{ obj.errors.age.0 }}</P>
            <P><input type="text" name="email"/>{{ obj.errors.email.0}}</P>
            -->
            <!--
             <p>{{ obj.as_p }}</p> 
            -->
            <p>{{ obj.as_p }}</p>
            <P>{{ obj.user }}{{ obj.errors.user.0 }}</P>
            <P>{{ obj.pwd }}{{ obj.errors.pwd.0 }}</P>
            <P>{{ obj.age }}{{ obj.errors.age.0 }}</P>
            <P>{{ obj.email }}{{ obj.errors.email.0}}</P>
            <input type="submit" value="提交"/>
        </form>

     Form类的内置字段

    Fields
            required = True,            #是否必填
            error_messages = {}          #自定义错误提示
            widget = widgets.Select(),   #定制HTML插件
            label = '用户名',            #{{obj.user.label}}
            initial = '请输入默认值',    #添加默认值
            help_text = '帮助文档',
            show_hidden_initial = True,  #是否在当前插件后面在加一个隐藏且具有默认值的插件(可用于检验两次输入是否一致)
            validators = [],             #自定制验证规则
            localize = False,            #是否支持本地化
            disabled = False,            #是否可编辑
            label_suffix = ':',          #后缀
    
    
    CharField(Fields)
            max_length = None,        #最大长度
            min_length = None,        #最小长度
            strip = True,             #是否移除空白
            error_messages = {'max_length': '太长了', 'min_length': '太短了'},   #自定义错误提示
    
    
    RegexField(CharField)
            regex,                  #自定制正则表达式
            error_messages=None,   #error_messages={'invalid':'格式错误的字段都是invalid'}
    
    
    URLField(CharField)
            ...
    
    
    EmailField(CharField)
            ...
        
    
    SlugField(CharField)      #数字,字母,下划线,减号(连字符)
            ...
    
    
    UUIDField(CharField)      #uuid类型
            ...
    
    
    FileField(Field)
            max_length = None,            #设置最大长度
            allow_empty_file = False,    #是否允许为空
    
    
    ImageField(FileField)
            ...
            注:需要PIL模块,pip3 install Pillow
            以上两个字典使用时,需要注意两点:
                - form表单中 enctype="multipart/form-data"
                - view函数中 obj = MyForm(request.POST, request.FILES)
    
    
    ChoiceField(Field)
            choices=(),             #选项,如:choices = ((0,'上海'),(1,'北京'),)
    
    
    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=''
    
    
    IntegerField(Fields)
            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 - 0111: 12
    
    DurationField(Field)  #时间间隔: % d % H: % M: % S. % f
            ...
    
    GenericIPAddressField
            protocol = 'both',      #both, ipv4, ipv6支持的IP格式
            unpack_ipv4 = False     #解析ipv4地址,如果是::ffff: 192.0.2.1时候,可解析为192.0.2.1, PS:protocol必须为both才能启用

    注:在使用选择标签时,需要注意choices的选项可以从数据库中获取,但是由于是静态字段 ***获取的值无法实时更新***,那么需要自定义构造方法从而达到此目的。

    方式一:

    from django.forms import Form
    from django.forms import widgets
    from django.forms import fields
    
    
    class MyForm(Form):
        user = fields.ChoiceField(
            # choices=((1, '上海'), (2, '北京'),),
            initial=2,
            widget=widgets.Select
        )
    
        def __init__(self, *args, **kwargs):
            super(MyForm, self).__init__(*args, **kwargs)
            # self.fields['user'].widget.choices = ((1, '上海'), (2, '北京'),)
            # 或
            self.fields['user'].widget.choices = models.Classes.objects.all().value_list('id', 'caption')  

    方法二:

    使用django提供的ModelChoiceField和ModelMultipleChoiceField字段来实现

    from django import forms
    from django.forms import fields
    from django.forms import widgets
    from django.forms import models as form_model
    
    
    class FInfo(forms.Form):
        authors = form_model.ModelMultipleChoiceField(queryset=models.NNewType.objects.all())
        # authors = form_model.ModelChoiceField(queryset=models.NNewType.objects.all())

    Form组件的验证扩展

     方法一:

    使用RegexValidator模块

    from django.forms import Form
    from django.forms import fields
    from django.core.validators import RegexValidator
    
    
    class MyForm(Form):
        user = fields.CharField(
            error_messages={'invalid': '.....'},
            validators=[RegexValidator(r'^[0-9]+$', '请输入数字'), RegexValidator(r'^159[0-9]+$', '数字必须以159开头')],
        )

    方法二:

    使用 RegexField字段

    from django.forms import Form
    from django.forms import widgets
    from django.forms import fields
    
    
    class MyForm(Form):
        user = fields.RegexField(r'^[0-9]+$',error_messages={'invalid':'.....'})

    方法三:

    自定义方法,自定义方法 clean_字段名

    from django.shortcuts import render
    from django import forms
    from django.forms import fields
    from django.forms import widgets
    from app03 import models
    # Create your views here.
    
    from django.core.exceptions import NON_FIELD_ERRORS, ValidationError
    
    
    class MyForm(forms.Form):
        username = fields.CharField()
        user_id = fields.IntegerField(
            widget=widgets.Select(choices=[(0, 'chen'), (1, 'xiaoyi'), (2, 'liu'), ])
        )
    
        # 自定义方法 clean_字段名
        # 必须返回值self.cleaned_data['username']
        # 如果出错:raise ValidationError('用户名已存在')
        def clean_username(self):
            v = self.cleaned_data['username']
            if models.UserInfo.objects.filter(username=v).count():
                # 自己详细错误信息
                raise ValidationError('用户名已存在')
            return v
    
        def clean_user_id(self):
            return self.cleaned_data['user_id']
    
        #整体的错误信息返回
        def clean(self):
            value_dict = self.cleaned_data
            v1 = value_dict.get('username')
            v2 = value_dict.get('user_id')
            if v1 == 'root' and v2 == 1:
                raise ValidationError('整体错误信息')
            return self.cleaned_data 

    在源码中会会通过反射去执行clean_"字段名"的方法,再将值赋值给self.cleaned_data[name]

        def _clean_fields(self):
            for name, field in self.fields.items():
                # value_from_datadict() gets the data from the data dictionaries.
                # Each widget type knows how to retrieve its own data, because some
                # widgets split data over several HTML fields.
                if field.disabled:
                    value = self.get_initial_for_field(field, name)
                else:
                    value = field.widget.value_from_datadict(self.data, self.files, self.add_prefix(name))
                try:
                    if isinstance(field, FileField):
                        initial = self.get_initial_for_field(field, name)
                        value = field.clean(value, initial)
                    else:
                        value = field.clean(value)
                    self.cleaned_data[name] = value
                    if hasattr(self, 'clean_%s' % name):
                        value = getattr(self, 'clean_%s' % name)()
                        self.cleaned_data[name] = value
                except ValidationError as e:
                    self.add_error(name, e)
  • 相关阅读:
    VS Studio中复制窗体产生obj\Debug\SXP227\newform2.resources”在“Resources”参数中指定了多次。“Resources”参数不支持重复项 错误解决方案
    标签 frameset, frame ,noframes,iframe
    Winform GridView的允许自动生成列属性 AutoGenerateColumns
    目前自己的.Net的水平状态评估、方向
    C# 读取Excel中的时间
    asp.net中Button控件的单击回传机制
    javascript实现两个asp.net服务器控件ListBox值的互传
    关键字partial
    解决jQuery插件tipswindown与hintbox冲突
    C#数据结构三:单链表Singly Linked List
  • 原文地址:https://www.cnblogs.com/shuzhixia/p/11180618.html
Copyright © 2020-2023  润新知