python-Django框架之【Form插件】
一、Form主要功能
1、生成HTML标签
2、验证用户数据(显示错误信息)
3、生成HTML代码, Form提交保留上次提交数据
4、初始化页面显示内容
二、使用流程
1、创建Form类
from django import forms class F1Form(forms.Form):
2、创建字段(包含正则表达式)
from django.forms import fields class F1Form(forms.Form): user = fields.CharField( min_length=6, max_length=12, required=True, error_messages={ "min_length":"长度不够", "max_length":"长度太长", "required":"不能为空"} )
事例:
1 from django import forms 2 from django.forms import fields 3 4 class F1Form(forms.Form): 5 user = fields.CharField( 6 min_length=6, 7 max_length=12, 8 required=True, 9 error_messages={ 10 "min_length":"长度不够", 11 "max_length":"长度太长", 12 "required":"不能为空"} 13 ) 14 pwd = fields.CharField( 15 min_length=6, 16 required=True, 17 error_messages={ 18 "min_length": "长度不够", 19 "required": "不能为空"} 20 ) 21 age = fields.IntegerField( 22 required=True, 23 error_messages={ 24 "required": "不能为空"} 25 ) 26 email = fields.EmailField( 27 required=True, 28 error_messages={ 29 "required": "不能为空", 30 "invalid":"格式不正确" 31 } 32 )
3、views中实例化Form类
is_valid():是否验证成功
cleaned_data:验证成功后要提交的数据(字典形式)
def index2(request): if request.method == "GET": obj = F1Form() #用于生成HTML代码 return render(request,"index2.html",{"obj":obj}) elif request.method == "POST": obj = F1Form(request.POST) #用于Form验证 if obj.is_valid(): #判断是否验证成功 return redirect("http://www.baidu.com") else: return render(request, "index2.html", {"obj": obj}):
4、前端
生成HTML代码
obj.errors:验证失败后的错误信息
<form action="/index2.html" method="post" novalidate> #也可以自己创建form表单元素,但是不会保留上一次输入的内容 {# <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>#} #通过obj = F1Form()自动生成form表单元素 <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> <p><input type="submit" value="提交"></p> </form>
注意:如果不用obj = F1Form()生成html代码,则form表单中的元素的name属性值必须与Form类的字段名一致
技巧:创建Form类时,字段名与models中的字段名(数据库字段名)一致,则验证成功后,直接提取obj.cleaned_data进行数据库记录的创建或修改(**obj.cleaned_data)。
1 if request.method == "GET": 2 obj = myforms.UserForm() 3 return render(request,"add_user.html",{"obj":obj}) 4 elif request.method == "POST": 5 obj = myforms.UserForm(request.POST) 6 if obj.is_valid(): 7 models.UserInfo.objects.create(**obj.cleaned_data) 8 return redirect("/users/") 9 else: 10 return render(request,"add_user.html",{"obj":obj})
三、Django内置字段及属性
每个字段都封装了一个正则表达式和默认的HTML插件
创建Form类时,主要涉及到 【字段】 和 【插件】,字段用于对用户请求数据的验证,插件用于自动生成HTML;
1 Field 2 required=True, 是否允许为空 3 widget=None, HTML插件 4 label=None, 用于生成Label标签或显示内容 5 initial=None, 初始值 6 help_text='', 帮助信息(在标签旁边显示) 7 error_messages=None, 错误信息 {'required': '不能为空', 'invalid': '格式错误'} 8 show_hidden_initial=False, 是否在当前插件后面再加一个隐藏的且具有默认值的插件(可用于检验两次输入是否一直) 9 validators=[], 自定义验证规则 10 localize=False, 是否支持本地化 11 disabled=False, 是否可以编辑 12 label_suffix=None Label内容后缀 13 14 15 CharField(Field) 16 max_length=None, 最大长度 17 min_length=None, 最小长度 18 strip=True 是否移除用户输入空白 19 20 IntegerField(Field) 21 max_value=None, 最大值 22 min_value=None, 最小值 23 24 FloatField(IntegerField) 25 ... 26 27 DecimalField(IntegerField) 28 max_value=None, 最大值 29 min_value=None, 最小值 30 max_digits=None, 总长度 31 decimal_places=None, 小数位长度 32 33 BaseTemporalField(Field) 34 input_formats=None 时间格式化 35 36 DateField(BaseTemporalField) 格式:2015-09-01 37 TimeField(BaseTemporalField) 格式:11:12 38 DateTimeField(BaseTemporalField)格式:2015-09-01 11:12 39 40 DurationField(Field) 时间间隔:%d %H:%M:%S.%f 41 ... 42 43 RegexField(CharField) 44 regex, 自定制正则表达式 45 max_length=None, 最大长度 46 min_length=None, 最小长度 47 error_message=None, 忽略,错误信息使用 error_messages={'invalid': '...'} 48 49 EmailField(CharField) 50 ... 51 52 FileField(Field) 53 allow_empty_file=False 是否允许空文件 54 55 ImageField(FileField) 56 ... 57 注:需要PIL模块,pip3 install Pillow 58 以上两个字典使用时,需要注意两点: 59 - form表单中 enctype="multipart/form-data" 60 - view函数中 obj = MyForm(request.POST, request.FILES) 61 62 URLField(Field) 63 ... 64 65 66 BooleanField(Field) 67 ... 68 69 NullBooleanField(BooleanField) 70 ... 71 72 ChoiceField(Field) 73 ... 74 choices=(), 选项,如:choices = ((0,'上海'),(1,'北京'),) 75 required=True, 是否必填 76 widget=None, 插件,默认select插件 77 label=None, Label内容 78 initial=None, 初始值 79 help_text='', 帮助提示 80 81 82 ModelChoiceField(ChoiceField) 83 ... django.forms.models.ModelChoiceField 84 queryset, # 查询数据库中的数据 85 empty_label="---------", # 默认空显示内容 86 to_field_name=None, # HTML中value的值对应的字段 87 limit_choices_to=None # ModelForm中对queryset二次筛选 88 89 ModelMultipleChoiceField(ModelChoiceField) 90 ... django.forms.models.ModelMultipleChoiceField 91 92 93 94 TypedChoiceField(ChoiceField) 95 coerce = lambda val: val 对选中的值进行一次转换 96 empty_value= '' 空值的默认值 97 98 MultipleChoiceField(ChoiceField) 99 ... 100 101 TypedMultipleChoiceField(MultipleChoiceField) 102 coerce = lambda val: val 对选中的每一个值进行一次转换 103 empty_value= '' 空值的默认值 104 105 ComboField(Field) 106 fields=() 使用多个验证,如下:即验证最大长度20,又验证邮箱格式 107 fields.ComboField(fields=[fields.CharField(max_length=20), fields.EmailField(),]) 108 109 MultiValueField(Field) 110 PS: 抽象类,子类中可以实现聚合多个字典去匹配一个值,要配合MultiWidget使用 111 112 SplitDateTimeField(MultiValueField) 113 input_date_formats=None, 格式列表:['%Y--%m--%d', '%m%d/%Y', '%m/%d/%y'] 114 input_time_formats=None 格式列表:['%H:%M:%S', '%H:%M:%S.%f', '%H:%M'] 115 116 FilePathField(ChoiceField) 文件选项,目录下文件显示在页面中 117 path, 文件夹路径 118 match=None, 正则匹配 119 recursive=False, 递归下面的文件夹 120 allow_files=True, 允许文件 121 allow_folders=False, 允许文件夹 122 required=True, 123 widget=None, 124 label=None, 125 initial=None, 126 help_text='' 127 128 GenericIPAddressField 129 protocol='both', both,ipv4,ipv6支持的IP格式 130 unpack_ipv4=False 解析ipv4地址,如果是::ffff:192.0.2.1时候,可解析为192.0.2.1, PS:protocol必须为both才能启用 131 132 SlugField(CharField) 数字,字母,下划线,减号(连字符) 133 ... 134 135 UUIDField(CharField) uuid类型 136 ... 137 138 139 140 注:UUID是根据MAC以及当前时间等创建的不重复的随机字符串
1 >>> import uuid 2 3 # make a UUID based on the host ID and current time 4 >>> uuid.uuid1() # doctest: +SKIP 5 UUID('a8098c1a-f86e-11da-bd1a-00112444be1e') 6 7 # make a UUID using an MD5 hash of a namespace UUID and a name 8 >>> uuid.uuid3(uuid.NAMESPACE_DNS, 'python.org') 9 UUID('6fa459ea-ee8a-3ca4-894e-db77e160355e') 10 11 # make a random UUID 12 >>> uuid.uuid4() # doctest: +SKIP 13 UUID('16fd2706-8baf-433b-82eb-8c7fada847da') 14 15 # make a UUID using a SHA-1 hash of a namespace UUID and a name 16 >>> uuid.uuid5(uuid.NAMESPACE_DNS, 'python.org') 17 UUID('886313e1-3b8a-5372-9b90-0c9aee199e5d') 18 19 # make a UUID from a string of hex digits (braces and hyphens ignored) 20 >>> x = uuid.UUID('{00010203-0405-0607-0809-0a0b0c0d0e0f}') 21 22 # convert a UUID to a string of hex digits in standard form 23 >>> str(x) 24 '00010203-0405-0607-0809-0a0b0c0d0e0f' 25 26 # get the raw 16 bytes of the UUID 27 >>> x.bytes 28 b'\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f' 29 30 # make a UUID from a 16-byte string 31 >>> uuid.UUID(bytes=x.bytes) 32 UUID('00010203-0405-0607-0809-0a0b0c0d0e0f')
四、Django内置插件
插件用于自动生成HTML标签
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
五、常用选择插件
导入:from django.forms import widgets
# 单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 # )
在使用选择标签时,需要注意choices的选项可以从数据库中获取,但是由于是静态字段 ***获取的值无法实时更新***,那么需要自定义构造方法从而达到此目的。
方式一:推荐使用
1 from django.forms import Form 2 from django.forms import widgets 3 from django.forms import fields 4 from django.core.validators import RegexValidator 5 6 class MyForm(Form): 7 8 user = fields.ChoiceField( 9 # choices=((1, '上海'), (2, '北京'),), 10 initial=2, 11 widget=widgets.Select 12 ) 13 14 def __init__(self, *args, **kwargs): 15 super(MyForm,self).__init__(*args, **kwargs) 16 # self.fields['user'].widget.choices = ((1, '上海'), (2, '北京'),) 17 # 或 18 self.fields['user'].widget.choices = models.Classes.objects.all().value_list('id','caption')
方式二:使用django提供的ModelChoiceField和ModelMultipleChoiceField字段来实现,需要models中类中包含__str__()方法配合,如果多个select,则无法实现,解耦性差。
1 from django import forms
2 from django.forms import fields
3 from django.forms import widgets
4 from django.forms import models as form_model
5 from django.core.exceptions import ValidationError
6 from django.core.validators import RegexValidator
7
8 class FInfo(forms.Form):
9 authors = form_model.ModelMultipleChoiceField(queryset=models.NNewType.objects.all())
10 # authors = form_model.ModelChoiceField(queryset=models.NNewType.objects.all())

浙公网安备 33010602011771号