• django之form组件


    一 创建一个form组件

     导入forms模块组件:from django import forms

     创建组件:创建一个类继承者forms.Form这个类

     类型:

      CharField:字符串类型,min_length:字符长度不能小于多少;max_length:字符的长度不能大于多少,error_messages:可以根据保存信息显示对应的中文报错,required:该字段不能够为空,widget:对input标签操作。

      IntegerField:整数类型,invalid:格式错误

      MultiplechioceField:设置字段为多选框(单选框)。initial=[数字,]:初始个数。choices=((value,数据),(value,数据)):为多选框(单选框赋值)。widgets.CheckboxSelectMultiple:设置为复选框

     其他类型:

    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类型
        ...
    View Code

     根据不同要求为表单加上不同的属性值:导入from django.forms impost widgets

      widgets.PasswoedInput:加上密文的属性值,addrs:为指定的标签加上属性。

      widgets.TextInput:文本信息

      widgets.Select:下拉菜单,choices:为option出入值和value属性值

     钩子clean:首先导入异常:from django.core.exceptions import ValidationError。

      局部钩子:clean_字段名,就是使用clean_加上一个字段名。用于字段校验

        raise calidationsError:抛出错误信息

        cleaned_data:如果符合条件,数据就会存放在这里面,可以使用get获取是一个有序的字典格式,从上往下依次判断添加。

     for name, field in self.fields.items():
                  try:
    
                        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)
    

      全局钩子:clean,直接在这个函数里面定义功能,可以用于多个字段的操作和比较,直接可以获取cleaned_data里面的数据。

        __all__:全局抛出来的错误存放在这个里面的。

            self.clean()     # def self.clean():return self.cleaned_data
            return  not self.errors    # True或者False    
    
    from django import forms
    from django.forms import widgets
    from django.core.exceptions import ValidationError
    
    
    class LoginForm(forms.Form):
    
        user=forms.CharField(min_length=5,max_length=12,
                             error_messages={
                                  "required":"该字段不能为空",
                                  "min_length":"该字段的长度不能小于5",
                                  "max_length":"该字段的长度不能大于12"},
                             widget=widgets.TextInput(attrs={"class":"form-control"})
                             )
    
    
        pwd=forms.CharField(
            error_messages={
                "invalid": "必须是数字"
            },
            widget=widgets.PasswordInput(attrs={"class":"form-control",})
        )
    
        gender=forms.CharField(
            widget=widgets.Select(choices=((1,''),(0,''),))
        )
    
        usersss = forms.MultipleChoiceField(
            initial=[2, ],
            choices=((1, '上海'), (2, '北京'),),
            widget=widgets.CheckboxSelectMultiple
        )
    
    
        def clean_user(self):
           print("============",self.cleaned_data.get("pwd"))  # ============ None
           if  not self.cleaned_data.get("user").isdigit():
    
               return self.cleaned_data.get("user")
           else:
               raise ValidationError("该字段不能是纯数字")
    
    
    
        def clean_pwd(self):
            print("-----------------",self.cleaned_data.get("user"))
            import re
            val=self.cleaned_data.get("pwd")
            ret=re.findall("^d{6}yuan$",val)
            if ret:
                return val
            else:
                raise ValidationError("密码不符合设定要求")
    
        def clean(self):
    
    
            if self.cleaned_data.get("user") and self.cleaned_data.get("pwd"):
                if self.cleaned_data.get("user") != self.cleaned_data.get("pwd"):
                    return self.cleaned_data
    
                else:
                    raise ValidationError("用户名与密码不能一致!")
    
            return self.cleaned_data
    View Code

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

    二 实例form对象

    实例化时:
            self.fields={
                "username":"字段规则对象",
                "password":"字段规则对象",
    
            }
    

     LoginForm:form自建实例的对象存放的地点,request.POST:将数据传递给对应的字段,绑定数据的表单实例

     is_valid:校验,将检验是否符合要求,返回的是一个布尔值

      cleaned_data:检验正确数据就存放在这里面,是以字典的格式存放的,出数据。

      errors:检验没有通过或错误的信息存放在这个里面,是以字典的格式存放的。errors.get获取里面的某些数据。

    from django.shortcuts import render,HttpResponse
    
    # Create your views here.
    
    from django import forms
    from .models import *
    
    from django.forms import widgets
    
    from .forms import *
    
    
    
    def login(request):
        if request.method=="POST":
            #print(request.POST) #<QueryDict: {'csrfmiddlewaretoken': ['0xrifjX7jplIZwngbrRjpHPXw6kyDVa2Erca0sGYfjH9UuDfHzNUdMzlh7EH2v44'], 'user': ['asdas'], 'pwd': ['12321321']}>
            login_form=LoginForm(request.POST) # 将数据传给对应字段  绑定数据的表单实例
    
            '''
                #   self.cleaned_data={"pwd":"12312412"}      
                #   self.errors={"user":"yuan",}
            '''
            if login_form.is_valid():
                print("通过验证")
                print(login_form.cleaned_data)
                print("use:",login_form.cleaned_data.get("user"))
                print(login_form.errors)
                ###############
                # user=login_form.cleaned_data.get("user")
                # pwd=login_form.cleaned_data.get("pwd")
                # UserInfo.objects.filter(username=user,password=pwd)
                # UserInfo.objects.filter(**login_form.cleaned_data)
    
                return HttpResponse("OK")
            else:
                # print("验证失败")
                # print(login_form.cleaned_data) # {'pwd': 77777}
                # print(login_form.errors)
                # ################## login_form.errors是什么类型
                # print(type(login_form.errors))# <class 'django.forms.utils.ErrorDict'>
                # ###################获取login_form.errors的某个键的值
                # print(login_form.errors.get("user"))
                # print(type(login_form.errors.get("pwd")))# <class 'django.forms.utils.ErrorList'>
                #
                # #login_form.errors={"user":["小于5位","不是数字"],"pwd":["",""]}
                errors=login_form.errors# {"user":["该字段不能是纯数字",],"pwd":["",""]}
                print("errors-->",errors)
    
                error_all=errors.get("__all__")
                return render(request, "login.html", {"login_form": login_form,"errors":errors,"error_all":error_all})
    
        #### get请求
    
        login_form=LoginForm()   # form组件的实例对象   未绑定表单实例
        return render(request,"login.html",{"login_form":login_form})
    View Code

    三 html文件渲染

     模板导入input标签:直接用对象.字段取出内容  {{ 对象.字段}}

     模板导入错误信息:直接使用srrors.字段名.0取出数据{{ srrors.字段名.0 }}

     form组件只能够直接渲染input标签,form标签还是需要自己写的。

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <!-- 新 Bootstrap 核心 CSS 文件 -->
        <link rel="stylesheet" href="//cdn.bootcss.com/bootstrap/3.3.5/css/bootstrap.min.css">
        <style>
            .container{
                margin-top: 100px;
    
            }
        </style>
    </head>
    <body>
    
    
    <div class="container">
        <div class="row">
            <div class="col-md-6">
    
                <form action="/login/" method="post">
                     {% csrf_token %}
                      <div class="form-group">
                        <label for="user">user</label>
                        {{ login_form.user }} <span>{{ errors.user.0 }}</span>
                      </div>
                      <div class="form-group">
                        <label for="pwd">pwd</label>
                        {{ login_form.pwd }} <span>{{ errors.pwd.0 }}</span>
                      </div>
                       <div class="form-group">
                        <label for="gender">gender</label>
                        {{ login_form.gender }}<span>{{ error_all.0 }}</span>
                      </div>
    
                     <p>{{ login_form.usersss }}</p>
    
                      <button type="submit" class="btn btn-default">Submit</button>
                    </form>
                <hr>
    {#            <form action="">#}
    {#                {{ login_form.as_p }}#}
    {#            </form>#}
    
            </div>
        </div>
    </div>
    
    </body>
    </html>
    View Code

    四 其他渲染对象

    对于<label>/<input> 对,还有几个输出选项:

    • {{ form.as_table }} 以表格的形式将它们渲染在<tr> 标签中
    • {{ form.as_p }} 将它们渲染在<p> 标签中
    • {{ form.as_ul }} 将它们渲染在<li> 标签中

    注意,你必须自己提供<table> 或<ul> 元素。

    {{ form.as_p }}结果如下:

    <form action="">
        <p>
            <label for="id_username">Username:</label>
            <input id="id_username" maxlength="100" name="username" type="text" required="">
        </p>
     
     
        <p>
            <label for="id_password">Password:</label>
            <input id="id_password" maxlength="100" name="password" placeholder="password" type="password" required="">
        </p>
     
     
        <p>
            <label for="id_telephone">Telephone:</label> <input id="id_telephone" name="telephone" type="number" required="">
        </p>
     
     
        <p>
            <label for="id_email">Email:</label> <input id="id_email" name="email" type="email" required="">
        </p>
     
     
        <p>
            <label for="id_is_married">Is married:</label> <input id="id_is_married" name="is_married" type="checkbox">
        </p>
     
     
        <input type="submit" value="注册">
    </form>
    View Code

     这种渲染有了限制,不能个自定义的渲染,而是将所有的字段全部渲染过去。

    手动渲染:我们没有必要非要让Django 来分拆表单的字段;如果我们喜欢,我们可以手工来做每个字段都是表单的一个属性,可以使用{{ form.name_of_field }} 访问,并将在Django 模板中正确地渲染

    <div class="fieldWrapper">
        {{ form.Username.errors }}
        {{ form.Username.label_tag }}
        {{ form.Username }}
    </div>
    

     五 表单渲染的错误信息

    registerForm=RegisterForm(request.POST)
    print(type(registerForm.errors))                      #<class 'django.forms.utils.ErrorDict'>
    print(type(registerForm.errors["username"]))          #<class 'django.forms.utils.ErrorList'> 
    
    使用{{ form.name_of_field.errors }} 显示表单错误的一个清单,并渲染成一个ul。看上去可能像:
    <ul class="errorlist">
        <li>Sender is required.</li>
    </ul>
    
    

    补充练习:

    from django.shortcuts import render
    
    # Create your views here.
    from .models import UserInfor
    
    from django.forms import ModelForm
    from django import forms
    
    from .models import *
    
    print(City.objects.all().values_list("id","name"))
    
    # class RegForm(forms.Form):
    #     user = forms.CharField(max_length=32)
    #     #gender_tuple=(0,'上海'),(1,'北京'),(2,'保定')
    #     gender = forms.ChoiceField(choices =City.objects.all().values_list("id","name"))
    #
    #     def __init__(self,*args,**kwargs):
    #         super(RegForm,self).__init__(*args,**kwargs)
    #         #print("Ok")
    #         print(self.fields["gender"].choices)
    #         self.fields["gender"].choices=City.objects.all().values_list("id","name")
    
    
    '''
    class UserInfor(models.Model):
        user=models.CharField(max_length=32)
        gender=models.IntegerField(choices=((1,"男"),(2,"女")))
        city=models.ForeignKey("City",default=1)
        roles=models.ManyToManyField("Roles",default=1)
    |||||
    
    class UserInfor(forms.Form):
        user=forms.CharField()
        gender=forms.TypedChoiceField(choices=((1,"男"),(2,"女")))
        city=forms.ModelChoiceField(choices=City.objects.all())
        roles=forms.ModelMultipleChoiceField(choices=Roles.objects.all())
    '''
    
    class RegForm(ModelForm):
        class Meta:
            model=UserInfor
            fields="__all__"
    
    def reg(reqeust):
        form=RegForm()
        print(form.fields)
    
        return render(reqeust,"reg.html",{"form":form})
    View Code

     

  • 相关阅读:
    Cocos2d-iphone 为sprite添加双击的事件响应
    经典书单 —— 语言/算法/机器学习/深度学习/AI/CV/PGM
    经典网络站点、论坛、博客
    经典网络站点、论坛、博客
    Python 格式化输出 —— 小数转化为百分数
    Python 格式化输出 —— 小数转化为百分数
    移位运算与除法、取模运算
    移位运算与除法、取模运算
    火箭、飞行器、探测器的发射
    火箭、飞行器、探测器的发射
  • 原文地址:https://www.cnblogs.com/fangjie0410/p/8038598.html
Copyright © 2020-2023  润新知