Django之Form组件
- 生成HTML标签
- 验证用户数据(显示错误信息)
- HTML Form提交保留上次提交数据
- 初始化页面显示内容
小试牛刀
1、创建Form类
from django.forms import Form from django.forms import widgets from django.forms import fields class MyForm(Form): user = fields.CharField( widget=widgets.TextInput(attrs={'id': 'i1', 'class': 'c1'}) ) gender = fields.ChoiceField( choices=((1, '男'), (2, '女'),), initial=2, widget=widgets.RadioSelect ) city = fields.CharField( initial=2, widget=widgets.Select(choices=((1,'上海'),(2,'北京'),)) ) pwd = fields.CharField( widget=widgets.PasswordInput(attrs={'class': 'c1'}, render_value=True) )
2、View函数处理
from django.shortcuts import render, redirect from .forms import MyForm def index(request): if request.method == "GET": obj = MyForm() return render(request, 'index.html', {'form': obj}) elif request.method == "POST": obj = MyForm(request.POST, request.FILES) if obj.is_valid(): values = obj.clean() print(values) else: errors = obj.errors print(errors) return render(request, 'index.html', {'form': obj}) else: return redirect('http://www.google.com')
3、生成HTML
<form action="/" method="POST" enctype="multipart/form-data"> <p>{{ form.user }} {{ form.user.errors }}</p> <p>{{ form.gender }} {{ form.gender.errors }}</p> <p>{{ form.city }} {{ form.city.errors }}</p> <p>{{ form.pwd }} {{ form.pwd.errors }}</p> <input type="submit"/> </form>

<form method="POST" enctype="multipart/form-data"> {% csrf_token %} {{ form.xxoo.label }} {{ form.xxoo.id_for_label }} {{ form.xxoo.label_tag }} {{ form.xxoo.errors }} <p>{{ form.user }} {{ form.user.errors }}</p> <input type="submit" /> </form>
Form类
创建Form类时,主要涉及到 【字段】 和 【插件】,字段用于对用户请求数据的验证,插件用于自动生成HTML;
1、Django内置字段如下:
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')
Form的重点如下:
Form重点: - 字段 用于保存正则表达式 ChoiceField ***** MultipleChoiceField CharField IntegerField DecimalField DateField DateTimeField EmailField GenericIPAddressField FileField RegexField - HTML插件 不能生成<a> <div>等标签,只能生成form表单类的标签 用于生成HTML标签 每个field 里都有一个默认插件和一个正则表达式 , 可以通过widget来修改默认插件
2、Django内置插件:
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
案列如下:
注意:#label_suffix = '->' #Label内容后缀 只能在 obj.as_p、obj.as_ul、obj.as_table的情况下使用,把test.html改成 如下格式才生效
<body> <h1>我是test3界面</h1> {{ obj.as_p }} </body>

from django.shortcuts import render from django import forms from django.forms import fields class TestForm(forms.Form): user = fields.CharField ( required=True, # 是否必填 max_length=12, # 最大长度 min_length=3, # 最小长度 # error_messages={}, # 错误提示 # widget = widgets.Select(), # 定制HTML插件 label='用户名', # 此时前台显示的就是用户名 initial='请输入用户', # 在当前设置默认值,一般不用 一般用form初始化的时候进行设置 help_text='asdfasdf', #没什么用 show_hidden_initial = False,# 默认是false,设置成True 复制一行代码,右击界面查看源码 # validators=[] 自定制验证规则,可以自己写表达式 #label_suffix = '->' #Label内容后缀 ) age = fields.IntegerField( label='年龄', label_suffix='--->', max_value=12, min_value=5, error_messages={ 'max_value': '太大了' } ) #EmailField 是一个类,继承了CharField类,(看源码),所以它有CharField的所有属性 email = fields.EmailField( # label='邮箱' #如果不设置,默认是英文email 字段名称 initial='zhangsan@qq.com' #给字段设置默认值 ) #上传文件 obj = TestForm(request.POST,request.FILES) #文件必须加request.FILES #html界面必须加上 enctype="multipart/form-data" img = fields.FileField() """ TypedChoiceField继承了ChoiceField, TypedChoiceField多了一个函数进行转换coerce = lambda x: int(x), TypedChoiceField 和ChoiceField的区别就是是否进行内部转换,ChoiceField默认数字是字符串, 用TypedChoiceField数字就会转换成数字因为TypedChoiceField继承了fields,所以它也有fields下的CharField的特性 TypedChoiceField 和ChoiceField是单选 """ city = fields.TypedChoiceField( coerce=lambda x: int(x), #默认(1,'上海'), 里面的1是字符串,用它变成数字类型 choices= [(1,'上海'),(2,'北京'),(3,'南京')] , #设置数据源 initial=2, #设置默认值 ) #MultipleChoiceField是多选 bobby = fields.MultipleChoiceField( choices=[(1, '刚娘'), (2, '铁娘'), (3, '钢弹')], #设置数据源 initial=[1,3] #设置 默认值 ) #FilPeathField 显示文件下的所有内容 几乎不用 xoo = fields.FilPeathField ( path='app01' ) def test(request): if request.method == 'GET': #obj = TestForm({'user':'alex','age':28,'email':'zhaosan@qq.com'}) #初始化指定默认值 如果是多选用列表 obj = TestForm() #前台界面输入<p>{{ obj.user }}</p> 会自动生成对话框(因为自动生成了代码) return render(request,'test.html',{'obj':obj}) else: obj = TestForm(request.POST,request.FILES) #文件必须加request.FILES obj.is_valid() print('执行结果',obj.cleaned_data) return render(request,'test.html',{'obj':obj})

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1>我是test界面</h1> {#上传文件或者图片必须加上 enctype="multipart/form-data#} <form method="post" action="/test/" novalidate enctype="multipart/form-data"> {% csrf_token %} <p>{{ obj.user.label }} {{ obj.user }}</p> <p>{{ obj.age.label }}{{ obj.age }}</p> <p>{{ obj.email.label }}{{ obj.email }}</p> <p>{{ obj.img.label }}{{ obj.img }}</p> <p>{{ obj.city.label }}{{ obj.city }}</p> <p>{{ obj.bobby.label }}{{ obj.bobby }}</p> <p>{{ obj.xoo.label }}{{ obj.xoo }}</p> <p><input type="submit"></p> </form> </body> </html>

"""Django_lesson21 URL Configuration The `urlpatterns` list routes URLs to views. For more information please see: https://docs.djangoproject.com/en/1.8/topics/http/urls/ Examples: Function views 1. Add an import: from my_app import views 2. Add a URL to urlpatterns: url(r'^$', views.home, name='home') Class-based views 1. Add an import: from other_app.views import Home 2. Add a URL to urlpatterns: url(r'^$', Home.as_view(), name='home') Including another URLconf 1. Add an import: from blog import urls as blog_urls 2. Add a URL to urlpatterns: url(r'^blog/', include(blog_urls)) """ from django.conf.urls import include, url from django.contrib import admin from app02 import views as v2 urlpatterns = [ url(r'^admin/', include(admin.site.urls)), url(r'^test/', v2.test), ]
常用选择插件
# 单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 # )
常用选择插件案列:
1、

from django.shortcuts import render from django import forms from django.forms import fields from django.forms import widgets class TestForm(forms.Form): user = fields.CharField ( required=True, # 是否必填 max_length=12, # 最大长度 min_length=3, # 最小长度 # error_messages={}, # 错误提示 # widget = widgets.Select(), # 定制HTML插件 label='用户名', # 此时前台显示的就是用户名 initial='请输入用户', # 在当前设置默认值,一般不用 一般用form初始化的时候进行设置 help_text='asdfasdf', #没什么用 show_hidden_initial = False,# 默认是false,设置成True 复制一行代码,右击界面查看源码 # validators=[] 自定制验证规则,可以自己写表达式 #label_suffix = '->' #Label内容后缀 ) age = fields.IntegerField( label='年龄', label_suffix='--->', max_value=12, min_value=5, error_messages={ 'max_value': '太大了' } ) #EmailField 是一个类,继承了CharField类,(看源码),所以它有CharField的所有属性 email = fields.EmailField( # label='邮箱' #如果不设置,默认是英文email 字段名称 initial='zhangsan@qq.com' #给字段设置默认值 ) #上传文件 obj = TestForm(request.POST,request.FILES) #文件必须加request.FILES #html界面必须加上 enctype="multipart/form-data# img = fields.FileField() """ TypedChoiceField继承了ChoiceField, TypedChoiceField多了一个函数进行转换coerce = lambda x: int(x), TypedChoiceField 和ChoiceField的区别就是是否进行内部转换,ChoiceField默认数字是字符串, 用TypedChoiceField数字就会转换成数字因为TypedChoiceField继承了fields,所以它也有fields下的CharField的特性 TypedChoiceField 和ChoiceField是单选 """ city = fields.TypedChoiceField( coerce=lambda x: int(x), #默认(1,'上海'), 里面的1是字符串,用它变成数字类型 choices= [(1,'上海'),(2,'北京'),(3,'南京')] , #设置数据源 initial=2, #设置默认值 ) #MultipleChoiceField是多选 bobby = fields.MultipleChoiceField( choices=[(1, '刚娘'), (2, '铁娘'), (3, '钢弹')], #设置数据源 initial=[1,3] #设置 默认值 ) # #FilPeathField 显示文件下的所有内容 几乎不用 # xoo = fields.FilPeathField ( # path='app01' # ) #单选下拉框 方法一 xdb = fields.CharField( widget=widgets.Select( choices=[(1,'刚娘'),(2,'铁娘'),(3,'钢弹')] ) ) xdb = fields.IntegerField( widget=widgets.Select( choices=[(1, '刚娘'), (2, '铁娘'), (3, '钢弹')] ) ) #单选框 的方法二 xdb = fields.ChoiceField( choices=[(1, '刚娘'), (2, '铁娘'), (3, '钢弹')] ) # 多选框 只有这一种写法 xdb = fields.MultipleChoiceField( choices=[(1, '刚娘'), (2, '铁娘'), (3, '钢弹')], widget = widgets.SelectMultiple(attrs={'class':'c1'}) #attrs={'class':'c1'} 自定义属性 右击源码 ) #单选checkbox 是否选中按钮 xdb = fields.CharField( widget=widgets.CheckboxInput() ) #多选checkbox xdb = fields.MultipleChoiceField( choices=((1,'上海'),(2,'北京'),(3,'南京'),(4,'郑州'),), #选择列表 initial=[3,], #默认选中 widget=widgets.CheckboxSelectMultiple ) #单选RadioSelect xdb = fields.ChoiceField( choices=((1,'上海'),(2,'北京'),(3,'南京'),(4,'郑州'),), initial=4, widget=widgets.RadioSelect ) def test(request): if request.method == 'GET': #obj = TestForm({'user':'alex','age':28,'email':'zhaosan@qq.com'}) #初始化指定默认值 如果是多选用列表 obj = TestForm() #前台界面输入<p>{{ obj.user }}</p> 会自动生成对话框(因为自动生成了代码) return render(request,'test.html',{'obj':obj}) else: obj = TestForm(request.POST,request.FILES) #文件必须加request.FILES obj.is_valid() print('执行结果',obj.cleaned_data) return render(request,'test.html',{'obj':obj})

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1>我是test界面</h1> {#上传文件或者图片必须加上 enctype="multipart/form-data#} <form method="post" action="/test/" novalidate enctype="multipart/form-data"> {% csrf_token %} <p>{{ obj.user.label }} {{ obj.user }}</p> <p>{{ obj.age.label }}{{ obj.age }}</p> <p>{{ obj.email.label }}{{ obj.email }}</p> <p>{{ obj.img.label }}{{ obj.img }}</p> <p>{{ obj.city.label }}{{ obj.city }}</p> <p>{{ obj.bobby.label }}{{ obj.bobby }}</p> {# <p>{{ obj.xoo.label }}{{ obj.xoo }}</p>#} <p>{{ obj.xdb.label }}{{ obj.xdb }}</p> <p><input type="submit"></p> </form> </body> </html>

"""Django_lesson21 URL Configuration The `urlpatterns` list routes URLs to views. For more information please see: https://docs.djangoproject.com/en/1.8/topics/http/urls/ Examples: Function views 1. Add an import: from my_app import views 2. Add a URL to urlpatterns: url(r'^$', views.home, name='home') Class-based views 1. Add an import: from other_app.views import Home 2. Add a URL to urlpatterns: url(r'^$', Home.as_view(), name='home') Including another URLconf 1. Add an import: from blog import urls as blog_urls 2. Add a URL to urlpatterns: url(r'^blog/', include(blog_urls)) """ from django.conf.urls import include, url from django.contrib import admin from app02 import views as v2 urlpatterns = [ url(r'^admin/', include(admin.site.urls)), url(r'^test/', v2.test), ]
2、标签 加上 safe的使用案列
#方法一、如果前台渲染出对话框需要加safe: 我是text标签 {{ text |safe }} text = "<input type = 'text'/>" #方法二、此时前台无需加safe from django.utils.safestring import mark_safe text =mark_safe(text)

from django.shortcuts import render from django import forms from django.forms import fields from django.forms import widgets class TestForm(forms.Form): user = fields.CharField ( required=True, # 是否必填 max_length=12, # 最大长度 min_length=3, # 最小长度 # error_messages={}, # 错误提示 # widget = widgets.Select(), # 定制HTML插件 label='用户名', # 此时前台显示的就是用户名 initial='请输入用户', # 在当前设置默认值,一般不用 一般用form初始化的时候进行设置 help_text='asdfasdf', #没什么用 show_hidden_initial = False,# 默认是false,设置成True 复制一行代码,右击界面查看源码 # validators=[] 自定制验证规则,可以自己写表达式 #label_suffix = '->' #Label内容后缀 ) age = fields.IntegerField( label='年龄', label_suffix='--->', max_value=100, min_value=5, error_messages={ 'max_value': '太大了' } ) #EmailField 是一个类,继承了CharField类,(看源码),所以它有CharField的所有属性 email = fields.EmailField( # label='邮箱' #如果不设置,默认是英文email 字段名称 initial='zhangsan@qq.com' #给字段设置默认值 ) def test(request): if request.method == 'GET': #obj = TestForm({'user':'alex','age':28,'email':'zhaosan@qq.com'}) #初始化指定默认值 如果是多选用列表 obj = TestForm() #前台界面输入<p>{{ obj.user }}</p> 会自动生成对话框(因为自动生成了代码) #方法一、如果前台渲染出对话框需要加safe: 我是text标签 {{ text |safe }} text = "<input type = 'text'/>" #方法二、此时前台无需加safe from django.utils.safestring import mark_safe text =mark_safe(text) return render(request,'test.html',{'obj':obj,'text':text}) else: obj = TestForm(request.POST,request.FILES) #文件必须加request.FILES obj.is_valid() print('执行结果',obj.cleaned_data) return render(request,'test.html',{'obj':obj})

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1>我是test界面</h1> 我是text标签 {{ text }} <form method="post" action="/test/" novalidate > {% csrf_token %} <p>{{ obj.user.label }} {{ obj.user }}</p> <p>{{ obj.age.label }}{{ obj.age }}</p> <p>{{ obj.email.label }}{{ obj.email }}</p> <p><input type="submit"></p> </form> </body> </html>
Form表单如果后台是用ajax 案列:
1、ajax只能用HttpResponse返回,用redirect跳转无反应
2、json可以dump的只有常用python类型(列表,元组,字典) ,类无法dump
3、ajax 用 window.location.href = "http://www.baidu.com" //跳转到百度界面
4、ajax里用 data:$('#fm').serialize(), 提交整个表单
5、 dataType:'JSON', 指定数据类型

from django.shortcuts import render,redirect,HttpResponse from django import forms from django.forms import fields from django.forms import widgets from app01 import models class AjaxForm(forms.Form): price = fields.IntegerField() user_id = fields.IntegerField( widget=widgets.Select( choices=[(0,'alex'),(1,'jack'),(2,'wusir')] ) ) #json可以dump的只有常用python类型(列表,元组,字典) ,类无法dump def ajax(request): if request.method=='GET': obj = AjaxForm() return render(request,'ajax.html',{'obj':obj}) else: ret = {'status':'杨戬','message':None} import json obj = AjaxForm(request.POST) if obj.is_valid(): print('验证成功') ret['status'] = 'yes' print('验证成功23',obj.cleaned_data,ret,type(ret),json.dumps(ret),type(json.dumps(ret))) return HttpResponse(json.dumps(ret)) #ajax当时只能用HttpResponse返回 # return redirect('https://www.baidu.com/') #因为是ajax提交的,不是form提交 所以不会有任何反应 else: # print(obj.errors.as_ul()) 错误信息默认的类型 # print(obj.errors.as_json()) 错误的其他类型 # print(obj.errors.as_data()) print(type(obj.errors),obj.errors) from django.forms.utils import ErrorDict ret['message'] = obj.errors print('验证失败',obj.errors) return HttpResponse(json.dumps(ret))

"""Django_lesson21 URL Configuration The `urlpatterns` list routes URLs to views. For more information please see: https://docs.djangoproject.com/en/1.8/topics/http/urls/ Examples: Function views 1. Add an import: from my_app import views 2. Add a URL to urlpatterns: url(r'^$', views.home, name='home') Class-based views 1. Add an import: from other_app.views import Home 2. Add a URL to urlpatterns: url(r'^$', Home.as_view(), name='home') Including another URLconf 1. Add an import: from blog import urls as blog_urls 2. Add a URL to urlpatterns: url(r'^blog/', include(blog_urls)) """ from django.conf.urls import include, url from django.contrib import admin from app01 import views as v2 urlpatterns = [ url(r'^admin/', include(admin.site.urls)), url(r'^ajax/', v2.ajax), ]

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1>我是ajax界面</h1> <form id="fm" method="post" action="/ajax/"> {% csrf_token %} {{ obj.as_p }} <input type="button" value="ajax提交" id="btn"> </form> <script src="/static/jquery-3.1.1.js"></script> <script> $(function () { $('#btn').click(function () { $.ajax({ url:'/ajax/', type:'POST', dataType:'JSON', data:$('#fm').serialize(), success:function (arg) { if (arg.status == 'yes') { window.location.href = "http://www.baidu.com" //跳转到百度界面 } console.log(arg,typeof (arg),arg.status) } } ) }) }) </script> </body> </html>
Form表单扩展方法
1、自定义方法验证每个字段 self._clean_fields()
- 自定义方法 clean_字段名
- 必须返回值self.cleaned_data['username']
- 如果出错:raise ValidationError('用户名已存在')
- obj.is_valid() form表单是在这进行验证,可以看源码
案列:

from django.shortcuts import render,redirect,HttpResponse from django import forms from django.forms import fields from django.forms import widgets from app01 import models from django.core.exceptions import NON_FIELD_ERRORS, ValidationError class AjaxForm(forms.Form): username = fields.CharField() user_id = fields.IntegerField( widget=widgets.Select( choices=[(0,'alex'),(1,'jack'),(2,'wusir')] ) ) # 自定义方法 clean_字段名 # 必须返回值self.cleaned_data['username'] # 如果出错:raise ValidationError('用户名已存在') def clean_username(self): # 当正则表达式通过后执行clean_username的方法 username是字段方法 v = self.cleaned_data['username'] if models.UserInfo.objects.filter(username=v).count(): # 整体错了 一个字段错误,就是整体错误 print('结果1',v) raise ValidationError('用户名已经存在') # 当字段存在 自己详细错误信息 return v # 必须返回值 def clean_user_id(self):# 当正则表达式通过后执行clean_user_id的方法 user_id是字段名 return self.cleaned_data['user_id'] # 必须返回值 #json可以dump的只有常用python类型(列表,元组,字典) ,类无法dump def ajax(request): if request.method=='GET': obj = AjaxForm() return render(request,'ajax.html',{'obj':obj}) else: ret = {'status':'杨戬','message':None} import json obj = AjaxForm(request.POST) if obj.is_valid(): print('验证成功') ret['status'] = 'yes' print('验证成功23',obj.cleaned_data,ret,type(ret),json.dumps(ret),type(json.dumps(ret))) return HttpResponse(json.dumps(ret)) #ajax当时只能用HttpResponse返回 # return redirect('https://www.baidu.com/') #因为是ajax提交的,不是form提交 所以不会有任何反应 else: # print(obj.errors.as_ul()) 错误信息默认的类型 # print(obj.errors.as_json()) 错误的其他类型 # print(obj.errors.as_data()) print(type(obj.errors),obj.errors) from django.forms.utils import ErrorDict ret['message'] = obj.errors print('验证失败',obj.errors) return HttpResponse(json.dumps(ret))

"""Django_lesson21 URL Configuration The `urlpatterns` list routes URLs to views. For more information please see: https://docs.djangoproject.com/en/1.8/topics/http/urls/ Examples: Function views 1. Add an import: from my_app import views 2. Add a URL to urlpatterns: url(r'^$', views.home, name='home') Class-based views 1. Add an import: from other_app.views import Home 2. Add a URL to urlpatterns: url(r'^$', Home.as_view(), name='home') Including another URLconf 1. Add an import: from blog import urls as blog_urls 2. Add a URL to urlpatterns: url(r'^blog/', include(blog_urls)) """ from django.conf.urls import include, url from django.contrib import admin from app01 import views as v2 urlpatterns = [ url(r'^admin/', include(admin.site.urls)), url(r'^ajax/', v2.ajax), ]

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1>我是ajax界面</h1> <form id="fm" method="post" action="/ajax/"> {% csrf_token %} {{ obj.as_p }} <input type="button" value="ajax提交" id="btn"> </form> <script src="/static/jquery-3.1.1.js"></script> <script> $(function () { $('#btn').click(function () { $.ajax({ url:'/ajax/', type:'POST', dataType:'JSON', data:$('#fm').serialize(), success:function (arg) { if (arg.status == 'yes') { window.location.href = "http://www.baidu.com" //跳转到百度界面 } console.log(arg,typeof (arg),arg.status) } } ) }) }) </script> </body> </html>

from django.db import models class UserInfo(models.Model): username = models.CharField(max_length=32) age = models.IntegerField() email = models.EmailField() price = models.IntegerField() # Create your models here.
2、Form表单自定义方法(clean方法)验证所有字段 self._clean_form()
重置 clean方法完成所有字段验证

from django.db import models class UserInfo(models.Model): username = models.CharField(max_length=32) age = models.IntegerField() email = models.EmailField() price = models.IntegerField() # Create your models here.

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1>我是ajax界面</h1> <form id="fm" method="post" action="/ajax/"> {% csrf_token %} {{ obj.as_p }} <input type="button" value="ajax提交" id="btn"> </form> <script src="/static/jquery-3.1.1.js"></script> <script> $(function () { $('#btn').click(function () { $.ajax({ url:'/ajax/', type:'POST', dataType:'JSON', data:$('#fm').serialize(), success:function (arg) { if (arg.status == 'yes') { window.location.href = "http://www.baidu.com" //跳转到百度界面 } console.log(arg,typeof (arg),arg.status) } } ) }) }) </script> </body> </html>

"""Django_lesson21 URL Configuration The `urlpatterns` list routes URLs to views. For more information please see: https://docs.djangoproject.com/en/1.8/topics/http/urls/ Examples: Function views 1. Add an import: from my_app import views 2. Add a URL to urlpatterns: url(r'^$', views.home, name='home') Class-based views 1. Add an import: from other_app.views import Home 2. Add a URL to urlpatterns: url(r'^$', Home.as_view(), name='home') Including another URLconf 1. Add an import: from blog import urls as blog_urls 2. Add a URL to urlpatterns: url(r'^blog/', include(blog_urls)) """ from django.conf.urls import include, url from django.contrib import admin from app01 import views as v2 urlpatterns = [ url(r'^admin/', include(admin.site.urls)), url(r'^ajax/', v2.ajax), ]

from django.shortcuts import render,redirect,HttpResponse from django import forms from django.forms import fields from django.forms import widgets from app01 import models from django.core.exceptions import NON_FIELD_ERRORS, ValidationError class AjaxForm(forms.Form): username = fields.CharField() user_id = fields.IntegerField( widget=widgets.Select( choices=[(0,'alex'),(1,'jack'),(2,'wusir')] ) ) # 自定义方法 clean_字段名 # 必须返回值self.cleaned_data['username'] # 如果出错:raise ValidationError('用户名已存在') def clean_username(self): # 当正则表达式通过后执行clean_username的方法 username是字段方法 v = self.cleaned_data['username'] if models.UserInfo.objects.filter(username=v).count(): # 整体错了 一个字段错误,就是整体错误 print('结果1',v) raise ValidationError('用户名已经存在') # 当字段存在 自己详细错误信息 return v # 必须返回值 def clean_user_id(self):# 当正则表达式通过后执行clean_user_id的方法 user_id是字段名 return self.cleaned_data['user_id'] # 必须返回值 #所有字段 整体验证 def clean(self): value_dict = self.cleaned_data v1 = value_dict.get('username') v2 = value_dict.get('user_id') if v1 == 'root' and v2 == 1: raise ValidationError('所有字段验证,整体错误 信息') return self.cleaned_data #json可以dump的只有常用python类型(列表,元组,字典) ,类无法dump def ajax(request): if request.method=='GET': obj = AjaxForm() return render(request,'ajax.html',{'obj':obj}) else: ret = {'status':'杨戬','message':None} import json obj = AjaxForm(request.POST) if obj.is_valid(): #在这进行验证 print('验证成功') ret['status'] = 'yes' print('验证成功23',obj.cleaned_data,ret,type(ret),json.dumps(ret),type(json.dumps(ret))) return HttpResponse(json.dumps(ret)) #ajax当时只能用HttpResponse返回 # return redirect('https://www.baidu.com/') #因为是ajax提交的,不是form提交 所以不会有任何反应 else: # print(obj.errors.as_ul()) 错误信息默认的类型 # print(obj.errors.as_json()) 错误的其他类型 # print(obj.errors.as_data()) print(type(obj.errors),obj.errors) from django.forms.utils import ErrorDict ret['message'] = obj.errors print('验证失败',obj.errors) return HttpResponse(json.dumps(ret))
实时更新案列
方法一、
此时如果向数据库增加数据,前台不会更新,需要重启项目才会数据更新, pyhton manage.py runserver 127.0.0.1:8080

from django.shortcuts import render from django import forms from django.forms import fields from django.forms import widgets from app01 import models class LoveForm(forms.Form): price = fields.IntegerField() user_id = fields.IntegerField( # widget=widgets.Select(choices=[(0,'alex'),(1,'jack'),(2,'wusir')]) # 这样写就写死了 widget=widgets.Select(choices=models.UserInfo.objects.all().values_list('id','username')) #从数据库里提取数据 ) def love(request): obj = LoveForm() return render(request,'love.html',{'obj':obj})

from django.db import models class UserInfo(models.Model): username = models.CharField(max_length=32) email = models.EmailField(max_length=32)

"""Django_lesson21 URL Configuration The `urlpatterns` list routes URLs to views. For more information please see: https://docs.djangoproject.com/en/1.8/topics/http/urls/ Examples: Function views 1. Add an import: from my_app import views 2. Add a URL to urlpatterns: url(r'^$', views.home, name='home') Class-based views 1. Add an import: from other_app.views import Home 2. Add a URL to urlpatterns: url(r'^$', Home.as_view(), name='home') Including another URLconf 1. Add an import: from blog import urls as blog_urls 2. Add a URL to urlpatterns: url(r'^blog/', include(blog_urls)) """ from django.conf.urls import include, url from django.contrib import admin from app01 import views from app02 import views as v2 urlpatterns = [ url(r'^admin/', include(admin.site.urls)), url(r'^love/', v2.love), ]

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1>我是爱你的</h1> <h1>有缘千里来交配</h1> <p>价格:{{ obj.price }}</p> <p>姑娘:{{ obj.user_id }}</p> </body> </html>
解决上面的问题: 增加下面的内容
# 只要创建对象就会执行__init_ - 方法 ,此时就不用重启了。这样就可以实时更新了。也是自定制功能 def __init__(self,*args,**kwargs): # 初始化方法 super(LoveForm,self).__init__(*args,**kwargs) #继承父类 # 拷贝所有的静态字段,复制给self.fields,需要先进行赋值,否则无法找到 # 所以 # self.fields 不能放在super上面 self.fields['user_id'].widget.choices=models.UserInfo.objects.all().values_list('id','username')
代码:其他不变,变得只有views.py文件

from django.shortcuts import render from django import forms from django.forms import fields from django.forms import widgets from app01 import models class LoveForm(forms.Form): price = fields.IntegerField() user_id = fields.IntegerField( # widget=widgets.Select(choices=[(0,'alex'),(1,'jack'),(2,'wusir')]) # 这样写就写死了 widget=widgets.Select(choices=models.UserInfo.objects.all().values_list('id','username')) #从数据库里提取数据 ) # 只要创建对象就会执行__init_ - 方法 ,此时就不用重启了。这样就可以实时更新了。也是自定制功能 def __init__(self,*args,**kwargs): # 初始化方法 super(LoveForm,self).__init__(*args,**kwargs) #继承父类 # 拷贝所有的静态字段,复制给self.fields,需要先进行赋值,否则无法找到 # 所以 # self.fields 不能放在super上面 self.fields['user_id'].widget.choices=models.UserInfo.objects.all().values_list('id','username') def love(request): obj = LoveForm() return render(request,'love.html',{'obj':obj})
方法二、
通过ModelChoiceField 完成实时更新,不建议使用
此方法需要在models.py文件定义__str__方法: 否则返回的是类型 object
def __str__(self): return self.username

from django.shortcuts import render from django import forms from django.forms import fields from django.forms import widgets from app01 import models from django.forms.models import ModelChoiceField class LoveForm(forms.Form): price = fields.IntegerField() user_id = fields.IntegerField( # widget=widgets.Select(choices=[(0,'alex'),(1,'jack'),(2,'wusir')]) # 这样写就写死了 widget=widgets.Select(choices=models.UserInfo.objects.all().values_list('id','username')) #从数据库里提取数据 ) user_id2 = ModelChoiceField( queryset=models.UserInfo.objects.all(), to_field_name='id' #表示已那一列作为value 右击看代码,它可以做到实时更新,不建议使用,前台显示汉子 需要modle定义str方法 ) # 只要创建对象就会执行__init_ - 方法 ,此时就不用重启了。这样就可以实时更新了。也是自定制功能 def __init__(self,*args,**kwargs): # 初始化方法 super(LoveForm,self).__init__(*args,**kwargs) #继承父类 # 拷贝所有的静态字段,复制给self.fields,需要先进行赋值,否则无法找到 # 所以 # self.fields 不能放在super上面 self.fields['user_id'].widget.choices=models.UserInfo.objects.all().values_list('id','username') def love(request): obj = LoveForm() return render(request,'love.html',{'obj':obj})

from django.db import models class UserInfo(models.Model): username = models.CharField(max_length=32) email = models.EmailField(max_length=32) def __str__(self): return self.username

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1>我是爱你的</h1> <h1>有缘千里来交配</h1> <p>价格:{{ obj.price }}</p> <p>姑娘:{{ obj.user_id }}</p> <p>姑娘2:{{ obj.user_id2 }}</p> </body> </html>

"""Django_lesson21 URL Configuration The `urlpatterns` list routes URLs to views. For more information please see: https://docs.djangoproject.com/en/1.8/topics/http/urls/ Examples: Function views 1. Add an import: from my_app import views 2. Add a URL to urlpatterns: url(r'^$', views.home, name='home') Class-based views 1. Add an import: from other_app.views import Home 2. Add a URL to urlpatterns: url(r'^$', Home.as_view(), name='home') Including another URLconf 1. Add an import: from blog import urls as blog_urls 2. Add a URL to urlpatterns: url(r'^blog/', include(blog_urls)) """ from django.conf.urls import include, url from django.contrib import admin from app01 import views from app02 import views as v2 urlpatterns = [ url(r'^admin/', include(admin.site.urls)), url(r'^love/', v2.love), ]
在使用选择标签时,需要注意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())
自定义验证规则
方式一:
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.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]
初始化数据
在Web应用程序中开发编写功能时,时常用到获取数据库中的数据并将值初始化在HTML中的标签上。
1、Form
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.CharField() city = fields.ChoiceField( choices=((1, '上海'), (2, '北京'),), widget=widgets.Select )
2、Views
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')
3、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>
综合案例
1、通过自定义方法验证手机号
2、name字段如果包含金瓶2三个字 报 不符合价值观错误
3、密码和确认密码必须一致,如果不一致 报 密码不一致错误
4、所有字段验证通过插入数据库 代码如下:
访问网址:http://127.0.0.1:8800/login2/

"""django11_8 URL Configuration The `urlpatterns` list routes URLs to views. For more information please see: https://docs.djangoproject.com/en/1.11/topics/http/urls/ Examples: Function views 1. Add an import: from my_app import views 2. Add a URL to urlpatterns: url(r'^$', views.home, name='home') Class-based views 1. Add an import: from other_app.views import Home 2. Add a URL to urlpatterns: url(r'^$', Home.as_view(), name='home') Including another URLconf 1. Import the include() function: from django.conf.urls import url, include 2. Add a URL to urlpatterns: url(r'^blog/', include('blog.urls')) """ from django.conf.urls import url from django.contrib import admin from app1 import views urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^login2/', views.login2), ]

from django.db import models class UserInfo(models.Model): name = models.CharField(max_length=32) pwd = models.CharField(max_length=12,default='123') email = models.EmailField(null=True) mobile = models.CharField(max_length=11,null=True) def __str__(self): return self.name class City(models.Model): name = models.CharField(unique=True,max_length=16,null=False) def __str__(self): return self.name # Create your models here.

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1>这是login2界面</h1> <form method="post" action="/login2/" novalidate > {% csrf_token %} <p>{{ obj_form.name.label }} {{ obj_form.name }} {{ obj_form.errors.name.0 }}</p> <p>{{ obj_form.email.label }} {{ obj_form.email }} {{ obj_form.errors.email.0 }}</p> <p>{{ obj_form.pwd.label }} {{ obj_form.pwd }} {{ obj_form.errors.pwd.0 }}</p> <p>{{ obj_form.re_pwd.label }} {{ obj_form.re_pwd }} {{ obj_form.errors.re_pwd.0 }}</p> <p>{{ obj_form.mobile.label }} {{ obj_form.mobile }} {{ obj_form.errors.mobile.0 }}</p> <p> {{ obj_form.city.label }} {{ obj_form.city }} {{ obj_form.errors.city.0 }}</p> <p><input type="submit" value="提交"></p> </form> </body> </html>

from django.shortcuts import render,redirect,HttpResponse from app1 import models from django import forms from django.forms import fields from django.core.validators import RegexValidator #自定义验证方法需要导入(如验证手机号) from django.core.exceptions import NON_FIELD_ERRORS, ValidationError class MyForm(forms.Form): name=fields.CharField( min_length=6, max_length=12, label='用户名', error_messages={ 'min_length':'字段太短', 'max_length':'字段太长' } ) email= fields.EmailField( label='邮箱', error_messages={ 'invalid': '邮箱格式错误' } ) pwd = fields.CharField( label='密码', min_length=6, max_length=12, error_messages={ 'min_length': '密码太短', 'max_length': '密码太长', 'required':'密码不允许为空' } ) re_pwd = fields.CharField( label='确认密码', min_length=6, max_length=12, error_messages={ 'min_length': '密码太短', 'max_length': '密码太长', 'required': '确认密码不允许为空' } ) mobile = fields.CharField( label='手机号', required=True, # 自己定制手机号校验规则 validators=[ RegexValidator(r'^[0-9]+$', '手机号必须是数字') , RegexValidator(r'^1[3-9][0-9]{9}$', '手机格式有误') ], ) city = fields.MultipleChoiceField( label='城市', choices=models.City.objects.all().values_list('id','name'), #设置数据源 initial=[1,3] #设置 默认值 ) #在MyForm类里自定义 name字段的验证属性 验证某一个字段 def clean_name(self): username = self.cleaned_data['name'] user2 = self.cleaned_data.get('name') print('username',username,self.cleaned_data,user2) if '金瓶2' in username: raise ValidationError('不符合社会主义价值观') return username #验证表里的所有字段 如验证两次输入 密码是否一致 def clean(self): pwd_value = self.cleaned_data.get('pwd') re_pwd_value = self.cleaned_data.get('re_pwd') if pwd_value !=re_pwd_value: # print('密码不一致') self.add_error('re_pwd','两次输入密码不一致') #自定义添加一个错误 raise ValidationError('两次输入密码不一致') return self.cleaned_data def login2(request): if request.method == 'GET': city_list = models.City.objects.all().values_list('id','name') print('结果',city_list) obj_form = MyForm() return render(request,'login2.html',{'obj_form':obj_form}) elif request.method == "POST": obj_form = MyForm(request.POST) if obj_form.is_valid(): print('验证成功',obj_form.cleaned_data,obj_form.cleaned_data['name']) obj_dict= {} for x,v in obj_form.cleaned_data.items(): if x in('name','pwd','mobile','email'): obj_dict[x]=v print('obj_dict',obj_dict) models.UserInfo.objects.create(**obj_dict) return HttpResponse('登录成功') else: print('验证失败',obj_form.errors,type(obj_form.errors)) # print('验证失败',obj_form.errors,obj_form.errors.get('name'),obj_form.errors.get('name')[0]) # print('验证失败2',obj_form.errors['__all__'],obj_form.errors['__all__'][0]) # print('验证失败2',obj_form.errors[NON_FIELD_ERRORS],obj_form.errors[NON_FIELD_ERRORS][0]) return render(request,'login2.html',{"obj_form":obj_form})