一.功能
1.生成HTML标签,并保留提交的数据 <obj>=<form_class>()#后端 {{<obj>.<field_name>}}#前端;生成指定字段的<input> {{<obj>.as_<type>}}#前端;生成obj中所有内容构成的指定类型的标签 #不推荐(定制样式时难以定位) 2.验证用户请求中的数据(显示错误信息) <obj>=<form_class>(**<data>)#后端;进行验证 <bool>=<obj>.is_valid()#后端;返回表示是否验证成功的bool <obj>.cleaned_data#后端;由验证成功的数据构成的dict {{<obj>.errors.<field_name>}}#前端;指定字段的错误信息 3.初始化页面内容(生成的HTML标签中有默认值) <obj>=<form_class>(**<acq_data>)#后端 {{<obj>.<field_name>}}#前端;指定字段的HTML标签 如果以form表单的形式提交: 1.为GET形式的请求时,Form组件会生成HTML标签 2.提交数据时,Form组件会保留这些数据,如果验证成功,则刷新页面/跳转 3.如果验证失败,会重新渲染页面,Form组件再次生成HTML标签 4.且标签中会渲染出通过Form组件保留的之前提交的数据 以Ajax形式提交: 1.为GET形式的请求时,Form组件会生成HTML标签 2.提交数据时,会返回1个dict,其中封装了验证结果及相关信息 4.在回调函数中进行判断,如果验证成功,则通过回调函数刷新页面/跳转 5.如果验证失败,则显示错误信息 6.由于验证失败时不刷新页面,Form组件无需保留之前提交的数据二.Form类 1.创建Form类:
创建Form类时,主要涉及"字段"和"插件" 字段用于验证用户请求中的数据 插件用于自动生成HTML #创建Form类: from django import forms from django.forms import fields class <form_class>(forms.Form):#必须继承该类 <field_name>=fields.<field_type>(<key>=<value>) #参数说明: form_class:类的名称 field_name:字段名 field_type:字段类型 #可取的值见:一.2.(2) key=value:键值对形式的参数 #可取的值见:一.2.(2)2.内置字段类型及属性: 部分字段类型参见: https://www.cnblogs.com/limaomao/p/9255148.html
#所有类型的共用参数,来自Field:此处显示的是默认值 #注意:部分属性只有在通过第2种方法生成HTML标签时才有效 required=True:是否必填;为bool widget=None:定制插件 #取值参见:一.2.(3) label="<field_name>":用于在<input>前生成<label>以显示文本内容;为str 前端调用:{{obj.<field>.label}} 默认为该字段的名称 initial=None:初始值 help_text='':帮助信息(在标签旁边显示);为str 前端调用:{{obj.<field>.help_text}} error_messages={...}:错误提示 #此处省略默认值 value的格式:{"<field>":"<text>",#指定字段的错误提示 "required":"不能为空", "invalid":"格式错误"} show_hidden_initial=False:是否在当前插件后再加1个隐藏的具有默认值的插件 #可用于检验2次输入是否一致 validators=[]:自定义验证规则;为list localize=False:是否支持本地化 #如:在数据库中存储UTC时间,该参数设为True后,显示时按照本地配置变化(如显示本地时间) disabled=False:该插件的值是否可以编辑 label_suffix=None:label参数内容的后缀;为str ##################以下是某些字段独有的参数################## #某个类继承另1个类,则会有被继承的类的全部参数 #以下所有类都直接/间接继承自Field类,故都有Field类的参数 #实现原理:每个类中都封装了正则表达式(用于验证)和默认插件(用于生成HTML标签) #标$的为常用类型 $CharField(Field):str类型 max_length=None:最大长度;为num min_length=None:最小长度;为num strip=True:是否自动移除用户输入的空白值 $IntegerField(Field):int类型 max_value=None:最大值;为num min_value=None:最小值;为num FloatField(IntegerField):float类型 #可能存在误差 ... $DecimalField(IntegerField):固定精度的10进制小数类型 #没有误差;涉及小数时使用DecimalField,避免用FloatField max_value=None:最大值 min_value=None:最小值 max_digits=None:总长度;为int decimal_places=None:小数位长度;为int 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:错误信息("invalid"类型) 格式:error_messages={'invalid':'...'} $EmailField(CharField):邮箱类型 ... $FileField(Field):文件类型 allow_empty_file=False:是否允许空文件 $ImageField(FileField):图像类型 #注:需要PIL模块(pip3 install Pillow) ... #以上2个类型在使用时需要注意: 1.form表单中:enctype="multipart/form-data" 2.view函数中:obj=<form_class>(request.POST,request.FILES) URLField(Field):URL类型 ... BooleanField(Field):bool类型 ... NullBooleanField(BooleanField):可为空的bool类型 ... $ChoiceField(Field):下拉框类型 #后台得到的是str choices=(<choice1>,<choice2>...):选项 如:choices=((0,'上海'),(1,'北京'),) widget=None:插件;默认为select插件 #可取的值见:一.2.(3) initial=1:默认值(为第initial个选项);为int django.forms.models.ModelChoiceField ModelChoiceField(ChoiceField):从数据库中进行选择而得到选项的下拉框类型 queryset:如何查询数据库中的数据;为(Model中的)数据库查询语句 empty_label="---------":默认空显示内容 #下拉框中有1个非选项行,该参数即为在该行显示的内容 to_field_name=<primary_key>:将数据库中哪个字段的值用作HTML标签的value属性的值 默认为主键字段 limit_choices_to=None:在ModelForm中对queryset进行2次筛选 django.forms.models.ModelMultipleChoiceField ModelMultipleChoiceField(ModelChoiceField):从数据库中进行选择而得到选项的多选框类型 ... $TypedChoiceField(ChoiceField):进行数据转换的选择框类型 coerce=lambda <val>:<func>(<val>):对选中的每个值进行转换 empty_value='':默认值 $MultipleChoiceField(ChoiceField):多选框类型 #后台得到的是str list initial=None:默认值(为第initial个选项);为int list $TypedMultipleChoiceField(MultipleChoiceField):进行数据转换的多选框类型 coerce=lambda <val>:<func>(<val>):对选中的每个值进行转换 empty_value='':默认值 $ComboField(Field):使用多个验证的类型 fields=[...]:其他类型构成的list #如:既验证最大长度20,又验证邮箱格式 fields.ComboField(fields=[fields.CharField(max_length=20),fields.EmailField(),]) MultiValueField(Field) #为抽象类,子类中可以实现聚合多个字典去匹配1个值,要配合MultiWidget使用 SplitDateTimeField(MultiValueField):同样用于日期时间类型,但封装了3个插件(忽略) 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:是否允许文件夹路径 $GenericIPAddressField:IP地址类型 protocol='both':哪种IP地址合法 可为"both"/"ipv4"/"ipv6" unpack_ipv4=False:解析ipv4地址 如果为 ::ffff:192.0.2.1 时,可解析为192.0.2.1 #注意:protocol="both"时才能使用 SlugField(CharField):只能包含数字/字母/下划线(_)/减号(-) ... UUIDField(CharField):UUID类型 #UUID是根据MAC以及当前时间等创建的不重复的随机字符串 ... 关于UUID: >>> import uuid #make a UUID based on the host ID and current time >>> uuid.uuid1() # doctest: +SKIP UUID('a8098c1a-f86e-11da-bd1a-00112444be1e') #make a UUID using an MD5 hash of a namespace UUID and a name >>> uuid.uuid3(uuid.NAMESPACE_DNS, 'python.org') UUID('6fa459ea-ee8a-3ca4-894e-db77e160355e') #make a random UUID >>> uuid.uuid4() # doctest: +SKIP UUID('16fd2706-8baf-433b-82eb-8c7fada847da') #make a UUID using a SHA-1 hash of a namespace UUID and a name >>> uuid.uuid5(uuid.NAMESPACE_DNS, 'python.org') UUID('886313e1-3b8a-5372-9b90-0c9aee199e5d') #make a UUID from a string of hex digits (braces and hyphens ignored) >>> x = uuid.UUID('{00010203-0405-0607-0809-0a0b0c0d0e0f}') #convert a UUID to a string of hex digits in standard form >>> str(x) '00010203-0405-0607-0809-0a0b0c0d0e0f' #get the raw 16 bytes of the UUID >>> x.bytesb'\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f' #make a UUID from a 16-byte string >>> uuid.UUID(bytes=x.bytes) UUID('00010203-0405-0607-0809-0a0b0c0d0e0f')3.内置插件:
#功能: 用于生成输入标签(其实是内容为标签的str) #主要包括:<input>,<select>,<textarea>(即表单类的标签) #原理: 1.通过字符串拼接返回"<input ... >" 2.再通过view函数中的render()渲染成<input ... > #拼接和渲染部分的源码见上图(示例) #格式: from django.forms import widgets widget=widgets.<type>(attr=**attr_data) #参数说明: type:插件类型(常用的类型见下) attr_data:指定标签属性的dict widget:字段的widget属性 #常用插件类型: TextInput(<Input>) #为CharField及其子类的默认插件 NumberInput(<TextInput>) EmailInput(<TextInput>) URLInput(<TextInput>) PasswordInput(<TextInput>) HiddenInput(<TextInput>) Textarea(<Widget>) DateInput(<DateTimeBaseInput>) DateTimeInput(<DateTimeBaseInput>) TimeInput(<DateTimeBaseInput>) CheckboxInput Select(choices=[<choice1>,<choice2>...]) #为ChoiceField及其子类的默认插件 #参数说明: choice1,choice2...:指定选项(所有<xx>Select<xx>插件都有该参数) choice1格式:(<n>,<c>),n是选项编号,c是显示的选项 NullBooleanSelect SelectMultiple RadioSelect CheckboxSelectMultiple FileInput ClearableFileInput MultipleHiddenInput SplitDateTimeWidget SplitHiddenDateTimeWidget SelectDateWidget 关于渲染: 可通过以下方法解决浏览器默认不渲染str形式的HTML标签的问题: from django.utils.safestring import mark_safe txt="<input type='text'>"#浏览器不渲染 txt1=mark_safe(txt)#浏览器渲染 当然也可以在前端通过{{txt|safe}}的方式解决 在插件中已经进行了上述处理,故无需加上|safe4.常用字段的生成:
#单选radio,提交的值为str: user=fields.CharField( initial=2, widget=widgets.RadioSelect(choices=((1,'上海'),(2,'北京'),)) ) #或: user=fields.ChoiceField( choices=((1,'上海'),(2,'北京'),), initial=2, widget=widgets.RadioSelect ) #单选select,提交的值为str: user=fields.CharField( initial=2, widget=widgets.Select(choices=((1,'上海'),(2,'北京'),)) ) #或: user=fields.ChoiceField( choices=((1, '上海'), (2, '北京'),), initial=2, widget=widgets.Select ) #多选select,提交的值为list: user=fields.MultipleChoiceField( choices=((1,'上海'),(2,'北京'),), initial=[1,], widget=widgets.SelectMultiple ) #单选checkbox: user=fields.CharField( widget=widgets.CheckboxInput() ) #多选checkbox,提交的值为list user=fields.MultipleChoiceField( initial=[2, ], choices=((1, '上海'), (2, '北京'),), #1,2...是选项编号;"上海","北京"...是选项 widget=widgets.CheckboxSelectMultiple#(choices=((1,'上海'),(2,'北京'),)) #2处choices选1处即可,推荐单独写成1个属性 )三.初始化数据 1.语法:
时常要从数据库中获取到数据并将这些数据初始化在<input>上(即<input>中会有默认值) #在后端: <obj>=<form_class>(**<acq_data>):实例化自定义的Form类 #参数说明: form_class:类名 acq_data:用于初始化的数据(即<input>中的默认值) obj:返回自定义的Form类的实例 #在前端: {{<obj>.<field_name>}}:生成指定字段的<input> #生成的<input>中会有默认值 #参数说明: field_name:字段名 obj:自定义的Form类的实例2.实例:
#forms.py: from django.forms import Form,widgets,fields from django.core.validators import RegexValidator class MyForm(Form): user=fields.CharField() city=fields.ChoiceField( choices=((1,'上海'),(2,'北京'),), widget=widgets.Select ) #views.py: from django.shortcuts import render, redirect from .forms import MyForm def index(request): if request.method=="GET": values={'user':'root','city':2} obj=MyForm(values) return render(request,'index.html',{'form':obj}) elif request.method=="POST": return redirect('http://www.google.com') else: return redirect('http://www.google.com') <!--index.html:--> <form method="POST" enctype="multipart/form-data"> {% csrf_token %} <p>{{ form.user }} {{ form.user.errors }}</p> <p>{{ form.city }} {{ form.city.errors }}</p> <input type="submit"/> </form>