zoukankan      html  css  js  c++  java
  • django表单使用

    一、表单常用字段类型及参数

    表单可以自动生成html代码,每一个字段默认有一个html显示样式,大多数默认为输入框。

    字段相当于正则表达式的集合,能够对表单传入的数据进行校验,并且某一部分校验失败时会保留另一部分校验成功的值。

    使用表单时首先需要导入forms模块和forms的fields模块,再定义一个继承forms.Form的类,实例化后在模板中通过调用实例化对象的属性生成输入框。

    field:这个一般不直接使用,用于被其他字段继承

    required=True, 是否允许为空

    label=None, 用于生成显示内容,如果不定义label,则显示的内容为首字母大写的字段名

    initial=None, 初始值

    help_text='', 帮助信息(在标签旁边显示)

    error_messages=None, 例如 {'required': '不能为空', 'invalid': '格式错误'},是一个字典,key表示每一个表达式的code,value表示如果在对应的code上发生错误,后台可以捕捉到的错误信息并返给前台与用户交互,其中value又是一个列表

    show_hidden_initial=False, 是否在当前插件后面再加一个隐藏的且具有默认值的插件(可用于检验两次输入是否一直)

    validators=[], 自定义验证规则

    localize=False, 是否支持本地化

    disabled=False, 是否可以编辑

    label_suffix=None Label内容后缀

    widget=None, 生成HTML插件

    1.BooleanField(Field):布尔值,相当于单选框

    2.CharField(Field):字符串

    max_length最大长度,min_length最小长度,strip是否移除用户输入的空格

    3.EmailField(CharField):邮箱

    invalid格式是否合法

    4.IntegerField(Field):整数

    invalid格式是否合法、max_value最大值、min_value最小值

    5.FloatField(IntegerField):浮点类型

    6.DecimalField(IntegerField):浮点类型

    max_digits(总长度)、decimal_places(小数位长度)

    7.FileField(Field):上传文件、ImageField(Field)上传图片

    allow_empty_file是否允许空文件,上传文件需要在form表单指定enctype="multipart/form-data",并且要通过request.FILES接收

    upload_to:指定上传路径

    8.ChoiceField(Field):单选下拉列表

    9.MultipleChoiceField(ChoiceField):多选下拉列表

    10.TypedChoiceField(ChoiceField))

    可对传入的数据进行一次类型转化coerce = lambda x: int(x)

    11.GenericIPAddressField(CharField):ip地址

    protocol='both'表示同时支持ipv4和ipv6的地址

    12.DateField(BaseTemporalField),日期,2019-05-10,

    13.TimeField(BaseTemporalField),时间,14:23

    14.DateTimeField(BaseTemporalField),日期和时间,2019-05-10 14:23

    15.URLField:接收URL格式的字符串

    二、django内置插件

    使用django的内置html插件时,需要先导入forms模块的widgets模块,from django.forms import widgets。

    对于CharField字段,默认显示的是文本框,如果希望显示成单选、多选或下拉列表的形式,则需要用到widgets定制插件。

    TextInput(Input)
    EmailInput(TextInput)
    NumberInput(TextInput)
    RadioSelect(ChoiceWidget)
    Select(ChoiceWidget)
    SelectMultiple(Select)
    CheckboxInput(Input)
    CheckboxSelectMultiple(ChoiceWidget)
    Textarea(Widget)
    DateInput(DateTimeBaseInput)
    DateTimeInput(DateTimeBaseInput)
    TimeInput(DateTimeBaseInput)
    URLInput(TextInput)
    PasswordInput(TextInput)
    FileInput
    HiddenInput(TextInput)
    NullBooleanSelect
    ClearableFileInput
    MultipleHiddenInput
    SplitDateTimeWidget
    SplitHiddenDateTimeWidget
    SelectDateWidget

    1.定制单选radio、单选下拉列表、多选下拉列表、单选框和多选框:通过CharField、ChoiceField和MutipleChoiceField字段

    对于单选radio,第一种写法使用CharField字段,该字段默认显示为输入框,通过widget=widgets.RadioSelect插件定制为单选框样式,并将choices作为参数传递给该插件

    第二种写法使用ChoiceField字段,该字段默认显示为下拉列表,通过widget=widgets.RadioSelect插件定制为单选框样式,并将choices作为参数传递给该字段

    通过widgets定制插件时,可同时给字段加上自定义属性,例如如下hobby8和hobby9。

    #单选radio
    hobby1 = fields.CharField(label='爱好1',widget=widgets.RadioSelect(choices=((1,'篮球'),(2,'足球'),(3,'乒乓球'))),initial=1)
    hobby2 = fields.ChoiceField(label='爱好2',widget=widgets.RadioSelect,choices=((1,'篮球'),(2,'足球'),(3,'乒乓球')),initial=1)
    #单选下拉列表
    hobby3 = fields.CharField(label='爱好3',widget=widgets.Select(choices=((1,'篮球'),(2,'足球'),(3,'乒乓球'))),initial=3)
    hobby4 = fields.ChoiceField(label='爱好4', widget=widgets.Select,choices=((1, '篮球'), (2, '足球'), (3, '乒乓球')), initial=3)
    #多选下拉列表
    hobby5 = fields.CharField(label='爱好5', widget=widgets.SelectMultiple(choices=((1, '篮球'), (2, '足球'), (3, '乒乓球'))), initial=[1, 2])
    hobby6 = fields.MultipleChoiceField(label='爱好6', widget=widgets.SelectMultiple,choices=((1, '篮球'), (2, '足球'), (3, '乒乓球')), initial=[1,2])
    #单选框
    hobby7 = fields.CharField(label='是否同意',widget=widgets.CheckboxInput())
    #多选框
    hobby8 = fields.CharField(label='爱好8', widget=widgets.CheckboxSelectMultiple(choices=((1, '篮球'), (2, '足球'), (3, '乒乓球')),attrs={'name':'hobby8'}), initial=[1, 2])
    hobby9 = fields.MultipleChoiceField(label='爱好9',widget=widgets.CheckboxSelectMultiple(attrs={'name':'hobby9'}),choices=((1, '篮球'), (2, '足球'), (3,'乒乓球'),initial=[1, 2]) 
    定制radio、select和checkbox

            

    2.扩展正则

    如果某一字段自带的验证方法不足以进行验证,可以自定义验证方法,这需要通过RegexField字段或者validators=[]参数完成

    #单选radio
    hobby1 = fields.CharField(label='爱好1',widget=widgets.RadioSelect(choices=((1,'篮球'),(2,'足球'),(3,'乒乓球'))),initial=1)
    hobby2 = fields.ChoiceField(label='爱好2',widget=widgets.RadioSelect,choices=((1,'篮球'),(2,'足球'),(3,'乒乓球')),initial=1)
    #单选下拉列表
    hobby3 = fields.CharField(label='爱好3',widget=widgets.Select(choices=((1,'篮球'),(2,'足球'),(3,'乒乓球'))),initial=3)
    hobby4 = fields.ChoiceField(label='爱好4', widget=widgets.Select,choices=((1, '篮球'), (2, '足球'), (3, '乒乓球')), initial=3)
    #多选下拉列表
    hobby5 = fields.CharField(label='爱好5', widget=widgets.SelectMultiple(choices=((1, '篮球'), (2, '足球'), (3, '乒乓球'))), initial=[1, 2])
    hobby6 = fields.MultipleChoiceField(label='爱好6', widget=widgets.SelectMultiple,choices=((1, '篮球'), (2, '足球'), (3, '乒乓球')), initial=[1,2])
    #单选框
    hobby7 = fields.CharField(label='是否同意',widget=widgets.CheckboxInput())
    #多选框
    hobby8 = fields.CharField(label='爱好8', widget=widgets.CheckboxSelectMultiple(choices=((1, '篮球'), (2, '足球'), (3, '乒乓球')),
    attrs={'name':'hobby7'}), initial=[1, 2])
    hobby9 = fields.MultipleChoiceField(label='爱好9',widget=widgets.CheckboxSelectMultiple(attrs={'name':'hobby8'}),
    choices=((1, '篮球'), (2, '足球'), (3,'乒乓球'),initial=[1, 2]) 
    定制radio、select和checkbox

    通过validators=[]属性定制时,可以自定义多个规则RegexValidator,每一个规则的第一个参数为规则,第二个规则为对应的错误信息

    通过RegexField字段定制时,只能定制一个规则。

    三、表单使用实例

    1.forms的py文件

    class UserForm(forms.Form):
        username = fields.CharField(label='姓名',required=True,max_length=15,error_messages={'max_length':'too long'})
        age = fields.IntegerField(label='年龄',required=True,min_value=18,error_messages={'invalid':'请输入整数','min_value':'不符合劳动法'})
        birth = fields.DateField(label='入职时间',required=True)
        email = fields.EmailField(label='邮箱',required=True,error_messages={'invalid':'请输入有效格式的邮箱'})
        gender = fields.CharField(label='性别', widget=widgets.RadioSelect(choices=((1, ''), (2, ''))), initial=1)
        resume = fields.FileField(label='简历')
        city = fields.CharField(label='省份',widget=widgets.Select())
        hobby = fields.MultipleChoiceField(label='爱好',widget=widgets.CheckboxSelectMultiple(attrs={'name':'hobby8'}),
    choices=((1, '篮球'), (2, '足球'), (3, '乒乓球')),initial=[1,2])
        proto = fields.CharField(label='是否已阅协议', widget=widgets.CheckboxInput())
        def __init__(self,*args,**kwargs):
            super(UserForm,self).__init__(*args,**kwargs)
            self.fields['city'].widget.choices = Province.objects.all().values_list()
    #假设定义了一个省份的类存放在数据库,为了数据库的内容变化能在页面刷新时显示到页面上,需要进行init操作并将数据库的值赋值给city字段
    定义UserForm

    2.处理函数的py文件

    def add_user(request):
        if request.method == 'GET':
            obj = UserForm()  #实例化一个空的表单
            return render(request,'add_user.html',{'obj':obj})
        elif request.method =='POST':
            obj = UserForm(request.POST,request.FILES) #传入的文件需要通过request.FILES接收,其他通过request.POST接收,一起传递给表单类进行实例化
            if obj.is_valid(): #判断输入是否有效
                print(type(obj.fields))
                print(obj.fields)
                print(type(obj.cleaned_data))
                print(obj.cleaned_data) #打印输入内容
                print(obj.cleaned_data['username'])  #获取输入的username值
                print(obj.cleaned_data.get('email'))  #获取输入的email值
                UserInfo.object.create(**obj.cleaned.data)  # UserForm表单对应了数据库中的表UserInfo
            else:  
                print(type(obj.errors))
                print(obj.errors.get_json_data())#打印错误信息,如果需要打印错误信息,还需要在form中指定novalidate属性
            return render(request,'add_user.html',{'obj':obj})
        else:
            return redirect('http://www.baidu.com')
    处理函数

    ①obj.is_valid()方法

    obj.is_valid()表示判断输入是否满足Form各字段的要求,实例化一个非空的表单,在实例化的时候并没有生成html标签,也没有进行表单验证,生成html标签并且进行表单验证是在is_valid()时进行的。obj.cleaned_data表示键值和对应的输入值。

    如果在实例化表单的时候通过inital传值,即obj = UserForm(inital = (request.POST,request.FILES) ),在实例化的时候不会进行表单验证。

    ②obj.fields属性

    obj.fields表示表单的所有字段,类型为<class 'collections.OrderedDict'>。

    ③obj.cleaned_data属性

    在is_valid之前没有cleaned_data,cleaned_data是在进行验证之后才生成,类型为<class 'dict'>

    ④obj.errors

    obj.errors表示错误信息,类型为<class 'django.forms.utils.ErrorDict'>

    错误信息默认是以as_ul()进行显示的,其他显示方式还有as_data()、as_json()、as_text()、get_json_Data(),常用get_json_Data()。

    3.模板文件

    在渲染form对象时,可以以as_table表格、as_ul无序列表、as_p段落等方式进行渲染。

    <form action="add_user" method="post" enctype="multipart/form-data">  <!--如果需要上传文件,则form中应指定enctype属性为multipart/form-data-->
            {% csrf_token %}
            <table>
                {{ obj.as_table }} <!--将表单以表格形式渲染-->
            </table>
            <input type="submit">
        </form>
    模板文件

    页面显示内容为,并且如果按照要求输入数据,pycharm打印的信息如下。

    如果在form中指定invalidate属性,假设不输入年龄、不按格式输入邮箱,那么打印的错误信息如下

    另外一种模板渲染方式

    <form action="add_user" method="post" enctype="multipart/form-data" novalidate>  
        <!--如果需要上传文件,则form中应指定enctype属性为multipart/form-data-->
            {% csrf_token %}
             <p>{{ obj.username.label }}{{ obj.username }}{{ obj.errors.0 }}</p>
             <p>{{ obj.age.label }}{{ obj.age }}{{ obj.errors.0 }}</p>
             <p>{{ obj.birth.label }}{{ obj.birth }}{{ obj.errors.0 }}</p>
             <p>{{ obj.email.label }}{{ obj.email }}{{ obj.errors.0 }}</p>
             <p>{{ obj.gender.label }}{{ obj.gender }}{{ obj.errors.0 }}</p>
             <p>{{ obj.resume.label }}{{ obj.resume }}{{ obj.errors.0 }}</p>
             <p>{{ obj.city.label }}{{ obj.city }}{{ obj.errors.0 }}</p>
             <p>{{ obj.hobby.label }}{{ obj.hobby }}{{ obj.errors.0 }}</p>
             <p>{{ obj.proto.label }}{{ obj.proto }}{{ obj.errors.0 }}</p>
            <input type="submit">
    </form>
    另一种模板渲染方式

    四、表单与数据库是否重复验证

    上述方法已经可以可以对各字段进行格式、大小、长度等验证,但是表单提交的数据通常要写入数据库,为了防止写入违反唯一性约束的两条相同记录,还需要验证增加的数据是否已经在数据库中存在。

    1.对于单一字段

    可在表单类时同时定义表单的方法,方法名称为clean_验证字段名,假如上述例子UserForm表单对应了的数据库中的表UserInfo,假如UserInfo表中的username不可重复,那么在定义表单时可通过增加clean_username()方法实现。

    #from django.core.exceptions import ValidationError导入异常类
    class UserForm(forms.Form):
        username = fields.CharField(label='姓名',required=True,max_length=15,error_messages={'max_length':'too long'})
        ……
        def clean_username(self):  #定义clean_字段名的方法
            v= self.cleaned_data['username']  #
            if UserInfo.objects.filter(username=v).count():  #
                raise ValidationError('用户名已经存在','repeat') #抛出异常,第一个参数为error_message,第二个为code
            return v
    表单对单一字段验证

    2.对于多个字段

    在定义表单类的同时定义clean()方法,假如username和age字段不可同时重复

    #from django.core.exceptions import NON_FIELD_ERRORS, ValidationError  
    class UserForm(forms.Form):
        ……  
        def clean(self):
            value_dic = self.cleaned_data
            v1 = value_dic.get('username')
            v2 = value_dic.get('email')
            if UserInfo.objects.filter(username=v1,email=v2).count():
                raise ValidationError('total error')
            return value_dic
    表单对多个字段验证

    因为这一类错误不属于单一的字段,因此在errors中显示的错误字段为__all__(也即NON_FIELD_ERRORS),而在模板页面只能通过v.non_field_errors(小写)获取整体错误信息,不能通过v.__all__获取。

    表单字段类型可参考http://www.cnblogs.com/wupeiqi/articles/6144178.html

  • 相关阅读:
    [LeetCode][SQL]Rising Temperature
    google API的.NET库
    Google Reader的另一个开源的替代品Go Read
    C#中反射接受的字符串需要满足的Backus-Naur Form语法
    Windows的应用管理工具 PortableApps,Chocolatey和Ninite
    如何定制Windows系统右键菜单
    另一个有趣的Captcha 网站
    .gitignore模板
    遇到sql server的问题时如何排查
    如何传播你的代码
  • 原文地址:https://www.cnblogs.com/Forever77/p/10183932.html
Copyright © 2011-2022 走看看