Django学习笔记:Forms

表单介绍

HTML表单负责接收用户的输入,对输入进行合法格式判断,并将数据发送到服务器。一个HTML表单必须指定两样东西:发送数据的url地址,发送的HTTP方法(GET、POST)。

GET方法:将用户数据以?<键1>=<值1>&<键2>=<值2>&...形式拼接到url后面,通常用于请求数据、网页搜索的表单。

POST方法:组合表单的数据并进行编码,然后打包发送到服务器,数据不会出现在url中,通常用于保密信息的发送、大量数据的表单、二进制数据。


在input标签中

#对于form表单也是一样,如果前端不指定post方法,默认使用get方法。



表单字段(常用)

CharField

渲染类型:TextInput

输入空值的返回:empty_value设定的值

转换为对象:Unicode对象

验证:min_length,max_length(如果设置过)

可用的错误信息键:min_length,max_length,required

max_length:允许输入的最大长度

min_length:允许输入的最小长度

strip:默认为True,表示去除前后的空格

empty_value:输入为空时返回的值,默认为空字符串


EmailField

渲染类型:EmailInput

输入空值的返回:空字符串

转换为对象:Unicode对象

验证:用正则表达式验证表单的值,必须是合法邮件地址

可用的错误信息键:required,invalid

max_length:允许输入的最大长度

min_length:允许输入的最小长度


表单字段的参数

error_messages

error_messages={‘key’: ‘value’}

自定义错误提示信息,键是表单里同名的错误类型字符串,值是自定义的提示信息字符串。

其中的key包括:

required,无填写内容

invalid,非法字符

maxlength,超出长度上限


max_length

最大长度


min_length

最小长度


required

required=True/False

该字段必填/非必填。

当为True时,<表单对象>.clean(‘‘)和<表单对象>.clean(None)返回ValidationError异常。

当为False时,<表单对象>.clean(‘‘)和<表单对象>.clean(None)返回None。

 

label

label=’<显示值>’

字段渲染成HTML代码的提示词,默认在后面加冒号。

如字段name = forms.CharField(label=’Your Name’),显示为HTML的

<label for=”id_name”>Your name: </label>

<input id=”id_name” type="text" name="name" required />


label_suffix

label_suffix=’<字符>’

自定义字符,代替label生成显示值后面的冒号。


initial

initial=’<值>’

为表单元素定义初始值,即标签中的value=,可传入值和对象。

# initial不会作为数据提交,表单仍需要用户填写数据。

只能用initial传递初始值,如果在渲染表单的时候传递一个初始值字典,会触发表单的验证,此时输出的HTML页面可能包含验证错误。


widget

widget=<widget类>

指定渲染Widget时使用的widget类,即前端中的type类型。

可用attr参数传入一个字典,对widget添加CSS样式,如:

name = forms.CharField(widget=forms.TextInput(attrs={‘class’: ‘special’}) )

comment = forms.CharField(widget=forms.TextInput(attrs={‘size’: ‘40’}) )


help_text

help_text=’<文本>’

设定辅助性描述文本,相当于HTML的默认显示值。


validators

validators=[ ]

传入列表,包含对字段验证的函数,自定义验证方法的时候用。


localize

实现表单数据输入的本地化。


disabled

disabled=True/False

设置对字段禁用/启用编辑,禁用编辑后,即使非法篡改前端页面的属性向服务器提交,该字段值也会被忽略。



表单API

绑定数据的表单能够验证数据,然后生成HTML表单,未绑定的表单无法验证数据,可生成HTML空表单。

创建空表单:f = <表单名>form()#创建表单类的实例

表单绑定数据:data = {:}#字典键是表单的字段名,值是传入的数据

                          f = <表单名>form(data)

                          #传入空字典将创建一个数据为空的已绑定表单

forms.Form实例的数据无法自读,所以创建表单对象之后不可更改。


表单的绑定

<表单对象>.is_bound

判断表单是/否绑定了数据,返回True/False。


表单的数据错误验证

<表单对象>.is_valid()

验证表单数据合法性,返回True/False。.is_valid()实际就是检查<表单对象>.errors是否为空,如果errors列表为空,就把所有数据储存到<表单对象>.cleaned_data字典中。


<表单对象>.errors

包含所有错误信息的字典类型,键是表单字段名,值是由错误信息组成的字符串形列表。


<表单对象>.errors.as_data()

返回错误信息的字典形式,将字段映射到原始的ValidationError实例,如:

{'sender': [ValidationError(['Enter a valid email address.']) ],

'subject': [ValidationError(['This field is required.']) ] }


<表单对象>.errors.as_json()

错误信息字典的JSON序列化形式,如:

{"sender": [{"message": "Enter a valid email address.", "code": "invalid"}],

"subject": [{"message": "This field is required.", "code": "required"}] }


<表单对象>.add_error(<字段名>, <错误信息>)

向表单的指定字段添加错误信息。


<表单对象>.has_error(<字段>, code=xxx)

判断某个字段是/否有指定的xxx错误,返回True/False。当code=None时,该字段有任何错误都返回True。


<表单对象>.non_field_errors()

返回<表单对象>.errors中不是与特定字段关联的错误。

 

表单的cleaned_data数据

①如果数据验证通过,把所有数据储存到<表单对象>.cleaned_data字典中;如果数据验证不通过,只把合法的数据存到<表单对象>.cleaned_data字典中。

②cleaned_data只包含Form类中的字段,如果传递额外数据,将不被储存。

③传递的数据不包含Form类中的某字段,cleaned_data中依然包含该键值对,显示为空值。


表单的数据更改验证

<表单对象>.has_changed()

检查表单数据是否从初始值发生改变,有改变返回True,无改变返回False,如:

data = <字典>

f = ContactForm(request.POST, initial=data)      # POST和data内容不一样

f.has_changed()


<表单对象>.changed_data

返回表单中有数据变化的字段的列表,如:

f = ContactForm(request.POST, initial=data)      # POST和data内容不一样

print(“, “.join(f.changed_data) )


表单的HTML生成

form类不包含<form></form>标签和<input type=”submit”>提交按钮,为方便开发人员自行编写控制表单动作和CSS,JS及如bootstrap框架的嵌入。

生成HTML标签的就是表单字段名,每个字段类型都由一个默认的HTML标签展示,可用widget参数指定生成的类型。

表单自动为每个input元素设置一个,用于的for参数。


{{ form.as_p }}

将每个字段渲染成标签。


{{ form.as_ul }}

将每个字段渲染成

标签(无序),

    标签需自己指定。


    {{ form.as_table }}

    将表单的每个字段渲染成标签,标签需自己指定。


    表单字段在前端的属性

    {{ field.value }}       当前字段的值,比如一个Email字段的值:someone@example.com

    {{ field.errors }}      包含错误信息的元素

    {{ field.label }}    字段的label信息

    {{ field.id_for_label }} 自定义字段标签的id

    {{ field.html_name }} 指定字段生成的input标签中name属性的值

    {{ field.help_text }} 字段的帮助信息

    {{ field.is_hidden }} 用于判断当前字段是否为隐藏的字段,隐藏则返回True

    {{ field.field }}      返回字段的参数列表,例如{{ char_field.field.max_length }}


    表单错误信息的CSS样式

    class <表单名>FORM(forms.Form):

        error_css_class = ‘error’

        required_css_class = ‘required’

        #其它表单字段...

    以后这个表单渲染HTML时将自动为error行和required行添加对应的CSS样式。


    表单上传文件

    没看懂,略。。。



    模型表单ModelForm

    基于model模型创建的表单,对模型的字段进行重用,根据model字段的限制进行表单验证。

    验证后,ModelForm.save()实际就是调用Model.save(),直接保存到数据库。


    from django.forms import ModelForm

    from <应用名>.models import <类>


    class <类名>Form(ModelForm):       #继承于ModelForm类

        class Meta:                     #设置元类Meta

            model = <类>               #设置model属性为某个模型类

            fields = [<字段1>, <字段2>, ...]      #用field属性传入列表,指定类中的字段

            fields = ‘__all__’                    #也可用field属性传入类的全部字段

            exclude = [<字段1>, <字段2>, ...]     #用exclude属性将排除的字段之外全部传入


    模型表单的保存

    <模型表单对象>.save(commit=True)       #将form表单的内容提交到数据库并保存

    如果没有commit=True就只提交,不保存


    指定数据对象

    form = ModelForm(instance=<绑定的Model对象>)

    此时可以直接form.save()将表单数据保存到数据表中。

    #如果不指定某个对象,save()时会在数据表中新增一行数据


    模型字段对应表单字段

    Model                           Form

    AutoField                        无对应

    BigAutoField                     无对应

    BigIntegerField                   IntegerField

    CharField                        相同,如果model设置null=True,Form将使用empty_value

    CommaSeparatedIntegerField      CharField

    ForeignKey                       ModelChoiceField

    ManyToManyField                 ModelMultipleChoiceField

    PositiveIntegerField                IntegerField

    PositiveSmallIntegerField           IntegerField

    SmallIntegerField                  IntegerField

    TextField                          CharField,属性widget=forms.Textarea

    模型字段设置blank=True属性,表单字段将设置required=False,反之相反。

    模型字段的verbose_name属性会设为表单字段的label属性,并将第一个字母大写。

    模型字段设置editable=False属性,表单类中将不会出现该字段,因为该字段不可编辑。

    模型字段的help_text属性即为表单字段的help_text属性。

    模型字段设置choices参数,表单字段的widget属性将设置为Select,其选项和模型字段相同。表单选项中通常会包含一个空选项作为默认,如果该字段必选,会强制用户选择一个选项;如果模型字段具有default参数,就不会在表单选项中添加空选项。


    模型表单的验证

    用.is_valid()方法或查询.errors列表,也可以重写模型表单的def clean()方法进行额外的验证,如:

    class <类名>Form(ModelForm):

        class meta:

            # ...


    def clean_<函数名>(self):

        #验证self.cleaned_data字典的数据...

        return <数据>


    自定义ModelForm字段

    使用元类Meta的widgets属性:

    class <类名>Form(ModelForm):

        class Meta:

            model = <类>

            fields = [‘<字段1>’, ...]

            widgets = {                        #传入字典,键是模型字段名,值是自定义的内容

                ‘<字段1>’:Textarea(attrs={‘cols’:80, ‘rows’:20} ),

                ...

            }


    ModelForm字段的本地化

    使用Meta类的localized_fields属性,传入一个元组,指定本地化的字段:

    class <类名>Form(ModelForm):

    class meta:

        model = <类>

        localized_fields = (‘<字段1>’, ...)       #传入’__all__’表示将类中的所有字段本地化




    表单示例

    ①在forms.py中:

    from django import forms


    class <表单名>Form(forms.Form):     #所有表单继承于forms.Form类

        sender = forms.EmailField()

        name = forms.CharField(label=’Your Name’, max_length=100)

        #一个字段代表中的一个元素,字段负责验证和转换数据

        # label用于设置说明标签,这里的max_length同时限制前端和后端的输入长度


    ②在views.py中:

    from .forms import <表单名>Form


    def get_name(request):

        if request.method == ’POST’:          #对于POST方法发送数据,接收数据并验证、处理

        a_form = <表单名>Form(request.POST)

        #用request.POST字典构造forms.Form类实例,将所有数据加载到表单中

            if a_form.is_valid():

                #处理表单数据...

                return HttpResponseRedirect(‘/xxx/’)    #处理成功,重定向到一个新url

        if request.method == ’GET’:                 #对于GET方法请求数据,返回空表单到模板

            a_form = <表单名>Form()


        return render(request, ‘xxx.html’, {‘form’: a_form}

    #处理不成功时,给用户返回这个模板。如果数据不合法,逻辑会在if a_form.is_valid()处断开,

    此时的a_form是包含原数据的表单,方便用户修改


    ③在templates中:

    <form action="/xxx/" method="post">          #写标签

        {% csrf_token %}

        {{ form }}                                 #表单模型生成的form表单元素

        <input type="submit" value="Submit" />      #写提交按钮

    </form>


    {{ form.<字段名> }}              获取表单的字段内容,用于手动渲染表单

    {{ form.<字段名>.label_tag }}      生成<label>标签,用于手动渲染表单

    {{ form.hidden_fields }}           表单中的不可见字段的集合

    {{ form.visible_fields }}            表单中的可见字段的集合




    表单模板的重用

    将表单模板保存为一个独立HTML文件,然后用{% include %}引用:

    {% include ‘xxxform.html’ %}

    {% for field in form %}

        #处理字段...

    {% endfor %}


    用with参数给表单取别名,防止名称冲突:

    {% include ‘xxxform.html’ with form=<别名> %}

    {% for field in <别名> %}

        #处理字段...

    {% endfor %}

    ©著作权归作者所有,转载或内容合作请联系作者
    • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
      沈念sama阅读 162,475评论 4 372
    • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
      沈念sama阅读 68,744评论 2 307
    • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
      开封第一讲书人阅读 112,101评论 0 254
    • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
      开封第一讲书人阅读 44,732评论 0 221
    • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
      茶点故事阅读 53,141评论 3 297
    • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
      开封第一讲书人阅读 41,049评论 1 226
    • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
      沈念sama阅读 32,188评论 2 320
    • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
      开封第一讲书人阅读 30,965评论 0 213
    • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
      沈念sama阅读 34,716评论 1 250
    • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
      茶点故事阅读 30,867评论 2 254
    • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
      茶点故事阅读 32,341评论 1 265
    • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
      沈念sama阅读 28,663评论 3 263
    • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
      茶点故事阅读 33,376评论 3 244
    • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
      开封第一讲书人阅读 26,200评论 0 8
    • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
      开封第一讲书人阅读 26,990评论 0 201
    • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
      沈念sama阅读 36,179评论 2 285
    • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
      茶点故事阅读 35,979评论 2 279

    推荐阅读更多精彩内容