form组件
form组件
一、form组件简介
1、form在组件的两大功能:
- 数据重置
- 校验规则
2、form组件于传统form表单对比
- 当我们用传统的form表单提交时会刷新页面,如果这个我们表单中的某项填错了,刷新后我们正确的选项也没有了.
- 传统的form表单需要我们自己亲自校验每一项,其工作量太大
-
form组件前端自动生成表单元素。
-
form组件可自动验证表单内容信息。
- form组件可保留用户上次输入的信息。
但是form表单的输出不包含submit
按钮,和表单的<form>
标签。 你必须自己提供。
二、form组件生成方法(三种)
1、方法一
1 2 3 4 5 6 7 | <form action = "/login/" method = "post" novalidate> { % csrf_token % } {{ form_obj.as_p }} #{{ form.as_p }}将它们渲染在<p> 标签中 {{ form_obj.as_table }} #{{ form.as_table }} 以表格的形式将它们渲染在<tr> 标签中 {{ form_obj.as_ul }} #{{ form.as_ul }将它们渲染在<li> 标签中 <p>< input type = "submit" value = "提交" >< / p> < / form>But:你必须自己提供<ul> 或 <table> 元素。 |
方式一示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | #HTML <form action = "/login/" method = "post" novalidate> #novalidate不对输入进行验证的表单 { % csrf_token % } {{ form_obj.as_p }} <p>< input type = "submit" value = "提交" >< / p> < / form> #views from . import models from django import forms from django.forms import widgets from django.core.exceptions import NON_FIELD_ERRORS,ValidationError class LoginForm(forms.Form): user = forms.CharField(max_length = 12 ,min_length = 5 , label = "用户名" , help_text = "6~16个字符,区分大小写" , error_messages = { "required" : "不能为空" , "min_length" : "最小长度为5" ,}) pwd = forms.CharField( help_text = "6~16个字符,区分大小写" , error_messages = { "invalid" : "格式错误" }, widget = widgets.PasswordInput(attrs = { "class" : "active" }) )<br><br> def login(request):<br><br> if request.method = = "POST" :<br><br> form_obj = LoginForm(request.POST)<br> if form_obj.is_valid():<br> # 数据全部合格<br> #取出合格数据<br> return HttpResponse("success")<br> else:<br> # 最少存在一个字段的错误<br> #取出错误信息<br> return render(request, "login.html", {"form_obj": form_obj}) #存放错误信息<br> form_obj = LoginForm()<br> return render(request,"login.html",{"form_obj":form_obj}) |
2、方法二(在任意标签中渲染)
1 2 3 4 5 6 7 8 9 10 11 12 13 | <form action = "/login/" method = "post" novalidate> { # novalidate不对输入进行验证的表单 { % csrf_token % } <div> <label for = "user" >用户名:< / label> {{ form_obj.user }} <span>{{ form_obj.errors.user. 0 }}< / span> < / div> <div> <label for = "pwd" >密码:< / label> {{ form_obj.pwd }}<span>{{ form_obj.errors.pwd. 0 }}< / span> < / div> <p>< input type = "submit" value = "提交" ><span>{{ ret. 0 }}< / span>< / p> < / form> |
3、方法三(for循环生成)
1 2 3 4 5 6 7 8 | <form action = "/login/" method = "post" novalidate> { % csrf_token % } { % for field in form_obj % } <div> <lable>{{ field.label }}< / lable> {{ field }} < / div> { % endfor % } |
三、表单验证的model加form方法
调取数据库进行验证:在models.py文件中创建一个类,在数据库中生成
创建的一个类:
生成的数据库:
views及forms代码:
form组件代码可建立一个form.py文件,然后在views中引入
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 | #form代码 class RegForm(forms.Form): user = forms.CharField(min_length = 5 ,max_length = 10 , error_messages = { "required" : "不能为空" , "min_length" : "最小长度为5" , }) pwd = forms.CharField( help_text = "6~16个字符,区分大小写" , widget = widgets.PasswordInput(attrs = { "class" : "active" }), error_messages = { "required" : "不能为空" , }) repwd = forms.CharField( help_text = "6~16个字符,区分大小写" , widget = widgets.PasswordInput(attrs = { "class" : "active" }), error_messages = { "required" : "不能为空" , } ) email = forms.EmailField( error_messages = { "required" : "不能为空" , "invalid" : "格式错误" }, ) tel = forms.CharField( error_messages = { "required" : "不能为空" , } ) def clean_user( self ): val = self .cleaned_data.get( "user" ) if val.isdigit(): raise ValidationError( "不能为数字" ) else : ret = UserInfo.objects. filter (name = val) if not ret: return val else : raise ValidationError( "该用户已注册" ) def clean_tel( self ): val = self .cleaned_data.get( "tel" ) import re #引入正则 ret = re.search( "^1[3578]\d{9}$" ,val) if ret: return val else : raise ValidationError( "手机号码格式" ) def clean( self ): repwd = self .cleaned_data.get( "repwd" ) pwd = self .cleaned_data.get( "pwd" ) if repwd = = pwd: return self .cleaned_data else : raise ValidationError( "两次密码不一致" ) views代码 def reg(request): if request.method = = "POST" : reg_form = RegForm(request.POST) if reg_form.is_valid(): name = reg_form.cleaned_data.get( "user" ) pwd = reg_form.cleaned_data.get( "pwd" ) UserInfo.objects.create(name = name,pwd = pwd) return redirect( "/login/" ) else : all_error = reg_form.errors.get( "__all__" ) return render(request, "register.html" , { "reg_form" : reg_form, "all_error" :all_error}) reg_form = RegForm() return render(request, "register.html" ,{ "reg_form" :reg_form}) #html代码 <h1>注册页面< / h1> <form action = "/reg/" method = "post" novalidate> { % csrf_token % } { % for field in reg_form % } <div> <lable>{{ field.label }}< / lable> {{ field }} <span>{{ field.errors. 0 }}< / span> { % if field.label = = "Repwd" % } { #field.label == "Repwd" Repwd是页面渲染后的名称#} <span>{{ all_error. 0 }}< / span> { % endif % } < / div> { % endfor % } <p>< input style = "margin-left: 100px" type = "submit" value = "注册" > < / form> |
四、form组件中常用字段及插件
Django中form的创建涉及到一些字段及插件
字段用于对用户请求数据的验证,插件用于自动生成HTML
1.Django内置字段
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 | 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类型 ... # 注:UUID是根据MAC以及当前时间等创建的不重复的随机字符串 >>> 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.bytes b '\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' ) |
2.Django内置插件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 | - - - - - - - - - - - - - - - - - - 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 - - - - - - - - - - - - - - - - - - 常用选择插件 # 单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的选项可以从数据库中获取,但是由于静态字段×××获取的值 # 无法实时更新×××,那么需要自定义构造方法从而达到此目的。 方法一. from django.forms import Form from django.forms import widgets from django.forms import fields from django.core.validators import RegexValidator class MyForm(Form): user = fields.ChoiceField( # choices=((1, '上海'), (2, '北京'),), initial = 2 , widget = widgets.Select ) def __init__( self , * args, * * kwargs): super (MyForm, self ).__init__( * args, * * kwargs) # self.fields['user'].widget.choices = ((1, '上海'), (2, '北京'),) # 或 self .fields[ 'user' ].widget.choices = models.Classes.objects. all ().value_list( 'id' , 'caption' ) 方法二. # 使用django提供的ModelChoiceField和ModelMultipleChoiceField字段来实现 from django import forms from django.forms import fields from django.forms import widgets from django.forms import models as form_model from django.core.exceptions import ValidationError from django.core.validators import RegexValidator class FInfo(forms.Form): authors = form_model.ModelMultipleChoiceField(queryset = models.NNewType.objects. all ()) # authors = form_model.ModelChoiceField(queryset=models.NNewType.objects.all()) |
五、form组件的校验
form组件自定义校验规则:
自定义校验规则中也会使用到局部钩子 跟 全局钩子 前边小例子中有涉及
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 | 方式一: from django.forms import Form from django.forms import widgets from django.forms import fields from django.core.validators import RegexValidator<br> form diango. class MyForm(Form): user = fields.CharField( validators = [RegexValidator(r '^[0-9]+$' , '请输入数字' ), RegexValidator(r '^159[0-9]+$' , '数字必须以159开头' )], ) 方式二: import re from django.forms import Form from django.forms import widgets from django.forms import fields from django.core.exceptions import ValidationError # 自定义验证规则 def mobile_validate(value): mobile_re = re. compile (r '^(13[0-9]|15[012356789]|17[678]|18[0-9]|14[57])[0-9]{8}$' ) if not mobile_re.match(value): raise ValidationError( '手机号码格式错误' ) class PublishForm(Form): title = fields.CharField(max_length = 20 , min_length = 5 , error_messages = { 'required' : '标题不能为空' , 'min_length' : '标题最少为5个字符' , 'max_length' : '标题最多为20个字符' }, widget = widgets.TextInput(attrs = { 'class' : "form-control" , 'placeholder' : '标题5-20个字符' })) # 使用自定义验证规则 phone = fields.CharField(validators = [mobile_validate, ], error_messages = { 'required' : '手机不能为空' }, widget = widgets.TextInput(attrs = { 'class' : "form-control" , 'placeholder' : u '手机号码' })) email = fields.EmailField(required = False , error_messages = { 'required' : u '邮箱不能为空' , 'invalid' : u '邮箱格式错误' }, widget = widgets.TextInput(attrs = { 'class' : "form-control" , 'placeholder' : u '邮箱' })) 方法三:自定义方法 from django import forms from django.forms import fields from django.forms import widgets from django.core.exceptions import ValidationError from django.core.validators import RegexValidator class FInfo(forms.Form): username = fields.CharField(max_length = 5 , validators = [RegexValidator(r '^[0-9]+$' , 'Enter a valid extension.' , 'invalid' )], ) email = fields.EmailField() def clean_username( self ): """ Form中字段中定义的格式匹配完之后,执行此方法进行验证 :return: """ value = self .cleaned_data[ 'username' ] if "666" in value: raise ValidationError( '666已经被玩烂了...' , 'invalid' ) return value 方法四:同时生成多个标签进行验证 from django.forms import Form from django.forms import widgets from django.forms import fields from django.core.validators import RegexValidator ############## 自定义字段 ############## class PhoneField(fields.MultiValueField): def __init__( self , * args, * * kwargs): # Define one message for all fields. error_messages = { 'incomplete' : 'Enter a country calling code and a phone number.' , } # Or define a different message for each field. f = ( fields.CharField( error_messages = { 'incomplete' : 'Enter a country calling code.' }, validators = [ RegexValidator(r '^[0-9]+$' , 'Enter a valid country calling code.' ), ], ), fields.CharField( error_messages = { 'incomplete' : 'Enter a phone number.' }, validators = [RegexValidator(r '^[0-9]+$' , 'Enter a valid phone number.' )], ), fields.CharField( validators = [RegexValidator(r '^[0-9]+$' , 'Enter a valid extension.' )], required = False , ), ) super (PhoneField, self ).__init__(error_messages = error_messages, fields = f, require_all_fields = False , * args, * * kwargs) def compress( self , data_list): """ 当用户验证都通过后,该值返回给用户 :param data_list: :return: """ return data_list ############## 自定义插件 ############## class SplitPhoneWidget(widgets.MultiWidget): def __init__( self ): ws = ( widgets.TextInput(), widgets.TextInput(), widgets.TextInput(), ) super (SplitPhoneWidget, self ).__init__(ws) def decompress( self , value): """ 处理初始值,当初始值initial不是列表时,调用该方法 :param value: :return: """ if value: return value.split( ',' ) return [ None , None , None ] |
局部钩子跟全局钩子案例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | from django import forms #调用forms模块 from django.forms import widgets #调用widgets模块,用来对form组件的参数配置。 from django.core.exceptions import ValidationError #调用 ValidationError 模块。用来手动触发raise错误。 from fileupdate.models import * #载入必要的数据库列表。 class FormReg(forms.Form): name = forms.CharField(min_length = 4 , widget = widgets.TextInput(attrs = { 'class' : 'form-control ' }), label = '姓名' , error_messages = { 'required' : '*不能为空' , }) pwd = forms.CharField(min_length = 4 , widget = widgets.PasswordInput(attrs = { 'class' : 'form-control' }), label = '密码' ) r_pwd = forms.CharField(min_length = 4 , widget = widgets.PasswordInput(attrs = { 'class' : 'form-control' }), label = '确认密码' ) email = forms.EmailField(widget = widgets.EmailInput(attrs = { 'class' : 'form-control' }), label = '邮箱' ) tel = forms.CharField(max_length = 13 , label = '电话' , widget = widgets.TextInput(attrs = { 'class' : 'form-control' })) ##字段的校验,通过对widget的属性设置,可定义INPUT标签的type类型,以及标签的其他属性。通过对label设置,可以自定义form渲染时的标签名, ##另外,通过对error_messages属性设置,可对验证信息进行自定义。注意:字典中错误信息的key值是固定的 def clean_name( self ): #局部钩子 注意:名字必须为clean_%s ,这是根据源码来设置的。 #其原理是,当字段校验完毕后,再进行查找是否有以clean_开头的函数名,如果有,就调用该函数, #运行我们自定义的函数,如果满足条件就返回当前被校验字段的内容。否则手动触发ValidationError错误,源码中会捕获并将值返回。 val = self .cleaned_data.get( 'name' ) #通过cleaned_data获得对应字段的'干净数据' user_obj = User.objects. filter (name = val).first() #与对应的数据库中字段相比较,并获得一个字段对象 if not user_obj: #对字段进行判断,如果为空(数据库中没有对应的名字),那么返回这个校验值。 return val else : raise ValidationError( '名字存在' ) #如果存在,那么手动触发异常(异常名为ValidationError),并设置自定义内容。 def clean( self ): #全局钩子 注意:名字必须为clean,这是根据源码来设置的。 #其原理是对校验完毕的字段,再进行字段间的校验。当字段校验完毕,查找是否有clean的函数,如果有就运行该 #函数,其功能是对所有校验的字段进行校验比对。如果满足条件,就将cleaned_data返回(这与源码相匹配) #如果不满足就手动触发ValidationError错误。 pwd = self .cleaned_data.get( 'pwd' ) r_pwd = self .cleaned_data.get( 'r_pwd' ) if pwd and r_pwd: #如果两个字段中一个为空值那么就不用再进行校验。直接返回cleaned_data,通过校验功能返回错误信息。 if pwd = = r_pwd: return self .cleaned_data else : raise ValidationError( '两次密码不一致!' ) else : return self .cleaned_data def reg(request): if request.method = = 'POST' : #如果是一次POST提交,那么进行校验。 formreg = FormReg(request.POST) #对提交的信息实例化。 if formreg.is_valid(): #通过is_valid()方法进行判断,(注意:当执行这个函数时,将对所有字段进行校验,运行局部钩子和全局钩子) return HttpResponse( 'OK' ) else : print ( 'cleaneddata' , formreg.cleaned_data) print ( 'errordata' , formreg.errors) error = formreg.errors.get( '__all__' ) #当设置了全局钩子时,要设置一个变量来获得全局钩子返回的错误信息。 #这是由于,全局钩子的错误在form对象的errors中,当clean()方法抛出异常时,源码会自动捕获,并将错误 #存储在errors字典中,其中键名'__all__'就是全局钩子的变量。 return render(request, 'reg.html' , locals ()) formreg = FormReg() #当为get请求时,实例化一个空的对象,通过这个空的实例化对象可以渲染前段,自动生成form表单。 return render(request, 'reg.html' , locals ()) |
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步