Python学习---DjangoForm的学习
DjangoForm之创建工程
Form是什么东西:
用于验证用户请求数据合法性的一个组件
普通的Form提交的弊端:
1.用户提交数据的验证
2.前台需要进行错误信息的提示
3.需要保留上次用户输入的信息
# 此处是正常的Form的判断操作 """ def Login(request): if request.method == "GET": return render(request, 'login.html') elif request.method == "POST": # 如果用户输入了10条数据,则Form里需要写10个get来获取值 user = request.POST.get("user") passwd = request.POST.get('passwd') email = request.POST.get('email') # 判断用户的输入[涉及用户的为空判断,输入格式内容校验以及数据库操作等判断] # 数据库校验: 传入参数校验 + 字典的传入校验 **kwargs # filter(user=u, email=e,passwd=p) ==> filter(**kwargs) # create(user=u, email=e,passwd=p) ==> create(**kwargs) # 如果校验失败,页面需要给用户显示错误信息,不能redirect[form提交页面会刷新,上次数据无法保留,ajax不涉及] 只能return render(request, 'login.html; 'args'arg),需要给前台HTML添加{{msg}}操作 """
查看Django为我们创建的正则:
DjangoForm的Form验证
Django的Form验证
- 控诉:
a. 用户提交数据的验证
1、创建模版 class LoginForm(forms.Form):...
2、将请求交给模版,创建一个对象 obj = LoginForm(request.POST)
3、进行验证 obj.is_valid()【必须执行,这里开始校验,否则clean获取不到值】
4、获取正确信息 obj.clean()
5、获取错误信息 obj.errors
b. 错误信息提示[传递Form对象给后台]
Form提交,刷新页面的特性,DjangoForm模版对象内部值丰富,再显示时,值和错误信息都有
c. 保留上一次提交的数据
1、自动生成html标签【实际上{{obj.user}} 就是内部生成了一个HTML的字符串】
2、保留上一次提交的数据【input框的value值更改为上次提交的值即可】
注:
obj对象里面有正确信息也有错误信息
Form使用 a,b,c
ajax使用 a,错误信息处理: as_json() as_data()
DjangoForm之前台参数校验实例
settings.py
INSTALLED_APPS = [ ... 'app01', # 注册app ] STATICFILES_DIRS = (os.path.join(BASE_DIR, "statics"),) # 现添加的配置,这里是元组,注意逗号 TEMPLATES = [ ... 'DIRS': [os.path.join(BASE_DIR, 'templates')], ]
urls.py
from django.contrib import admin from django.urls import path from django.conf.urls import url, include from app01 import views urlpatterns = [ path('admin/', admin.site.urls), url(r'login.html/', views.Login), ]
views.py
from django.shortcuts import render, redirect # 创建模板 # 本质是从请求中获取数据后来进行校验 from django import forms class LoginForm(forms.Form): # 前台Form表单里面的name属性的值必须跟这里的名称完全一致,这样数据提交后才能进行校验 # 如果名称不一致,则默认数据未传递过来,不作处理 # 如果传递多个参数,则模版默认只按照名称来进行匹配,有则匹配,无责不匹配 user = forms.CharField(min_length=6) # 模版元素 passwd = forms.CharField(min_length=12) # 模版元素 email = forms.EmailField(error_messages={"required": "格式错误"})# 模版元素同时自定义格式 """ code: required: 如果输入为空的时候显示 invalid: 输入的类型错误 min_length: 最小长度 """ def Login(request): if request.method == "GET": return render(request, 'login.html') elif request.method == "POST": # 模版会自动从request里面取值并校验 obj = LoginForm(request.POST) # 从模版里面开始验证,全部正确则显示结果正确,否则错误 status = obj.is_valid() print('验证结果:', status) if status: # 获取校验过的值和验证的错误信息 value_dict = obj.clean() print('验证通过的值:', value_dict) # 类.create(**value_dict) --> 此时可以直接插入数据到数据库了 else: error_dict = obj.errors # 此时的返回结果是个ErrorDict对象,可以type看类型 # <class 'django.forms.utils.ErrorDict'>该对象基础DICT这个里面有as_json和as_data方法 print('错误的信息[默认UL显示]:', error_dict) error_dict_json = obj.errors.as_json() # 此时的返回结果是个JSON集 print('错误的信息[json显示]:', error_dict_json) return render(request, 'login.html',{'obj': obj})
templates/login.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> </head> <body> <h1>Form提交数据</h1> <form method="post" action="/login.html/"> <!-- 前台的属组操作只能用点.来获取列表的第一个元素 --> <p><input type="text" name="user" placeholder="用户名"><span>{{ obj.user.errors.0}}</span></p> <p><input type="password" name="passwd" placeholder="密码"><span>{{ obj.passwd.errors.0}}</span></p> <p><input type="text" name="email" placeholder="邮箱"><span>{{ obj.user.email.0}}</span></p> <input type="submit" value="Form提交"> <input id='ajax_submit' type="button" value="Ajax提交"> </form> </body> <script src="/static/jquery-2.1.4.min.js"></script> <script> $(function () { $('#ajax_submit').click(function () { $.ajax({ url:"/login.html", data:{user:'omc', email:'omc@hhh.com', passwd:'lem600'}, type:'POST', success:function (args) { console.log(args) } }) }) }) </script> </html>
页面显示:
学习扩展:
# 封装Django里面的所有错误信息
error_dict = obj.errors # 此时的返回结果是个ErrorDict对象 print('错误的信息[UL显示]:', error_dict) # 这里返回的是一个对象 print('错误信息类型:', type(error_dict))#因为返回了ErrorDict里面__str__方法:return self.as_ul(); # 因为返回的是DICT对象,所以可以利用key获取 print('错误信息类型:', type(error_dict)) # 错误信息类型: <class 'django.forms.utils.ErrorDict'> #print('获取错误信息[属性获取]:', error_dict.user) # 错误,'ErrorDict' object has no attribute 'user' print('获取错误信息[key获取]:', error_dict['user']) # 正确 print('获取错误信息[key获取]类型:', type(error_dict['user'])) # ErrorList类型,默认返回第一个list[0] print('获取错误信息[此时是字符串]:', error_dict['user'][0]) # 字符串 This field is required.
DjangoForm之提交数据后保留数据
Django会自动生成HTML,并保留我们生成的数据
settings.py
INSTALLED_APPS = [ ... 'app01', # 注册app ] STATICFILES_DIRS = (os.path.join(BASE_DIR, "statics"),) # 现添加的配置,这里是元组,注意逗号 TEMPLATES = [ ... 'DIRS': [os.path.join(BASE_DIR, 'templates')], ]
urls.py
from django.contrib import admin from django.urls import path from django.conf.urls import url, include from app01 import views urlpatterns = [ path('admin/', admin.site.urls), url(r'login.html/', views.Login), ]
views.py
from django.shortcuts import render, redirect # 创建模板 # 本质是从请求中获取数据后来进行校验 from django import forms class LoginForm(forms.Form): # 前台Form表单里面的name属性的值必须跟这里的名称完全一致,这样数据提交后才能进行校验 # 如果名称不一致,则默认数据未传递过来,不作处理 # 如果传递多个参数,则模版默认只按照名称来进行匹配,有则匹配,无责不匹配 user = forms.CharField(min_length=6) # 模版元素 passwd = forms.CharField(min_length=12) # 模版元素 email = forms.EmailField(error_messages={"required": "格式错误"})# 模版元素同时自定义格式 """ code: required: 如果输入为空的时候显示 invalid: 输入的类型错误 min_length: 最小长度 """ def Login(request): if request.method == "GET": obj = LoginForm() # 这里生成的obj对象只有生成HTML的作用,但是名称必须跟后面POST对象一致 return render(request, 'login.html', {'obj': obj}) elif request.method == "POST": # 模版会自动从request里面取值并校验 obj = LoginForm(request.POST) # 从模版里面开始验证,全部正确则显示结果正确,否则错误 status = obj.is_valid() print('验证结果:', status) if status: # 获取校验过的值和验证的错误信息 value_dict = obj.clean() print('验证通过的值:', value_dict) # 类.create(**value_dict) --> 此时可以直接插入数据到数据库了 else: error_dict = obj.errors # 此时的返回结果是个ErrorDict对象,可以type看类型 # <class 'django.forms.utils.ErrorDict'>该对象基础DICT这个里面有as_json和as_data方法 print('错误的信息[默认UL显示]:', error_dict) error_dict_json = obj.errors.as_json() # 此时的返回结果是个JSON集 print('错误的信息[json显示]:', error_dict_json) return render(request, 'login.html',{'obj': obj})
templates/login.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> </head> <body> <h1>Form提交数据</h1> <form method="post" action="/login.html/"> <!-- 前台的属组操作只能用点.来获取,这里的表单是Django帮我们做的 --> <p>{{ obj.user }}<span>{{ obj.user.errors.0}}</span></p> <p>{{ obj.passwd }}<span>{{ obj.passwd.errors.0}}</span></p> <p>{{ obj.email }}<span>{{ obj.user.email.0}}</span></p> <input type="submit" value="Form提交"> <input id='ajax_submit' type="button" value="Ajax提交"> </form> </body> <script src="/static/jquery-2.1.4.min.js"></script> <script> $(function () { $('#ajax_submit').click(function () { $.ajax({ url:"/login.html", data:{user:'omc', email:'omc@hhh.com', passwd:'lem600'}, type:'POST', success:function (args) { console.log(args) } }) }) }) </script> </html>
页面显示;
问题:为什么get的Form对象必须和Form的一致?
答: get请求过来后我们实例化了一个不带参数的LoginForm的obj对象,此时的只能在前台生成HTML作用[前台obj.user]
post请求提交数据后,我们实例化了一个带POST参数的LoginForm的obj对象,里面有我们前台请求的数据,此时obj对象具有1.生成前台HTML的作用 2.带了post参数可以直接前台显示 3.我们前台用来同一个模板{{ }}来接收数据【正确/错误信息】,所以obj对象的名称不能改
如果我们更改POST对象名称为obj1,前台也更改为obj1,此时数据提交后就不再显示input框了,因为一个是obj,一个是obj1
附:input标签的生成过程[源码分析]
DjangoForm的Ajax验证【代码有问题】
settings.py
INSTALLED_APPS = [ ... 'app01', # 注册app ] STATICFILES_DIRS = (os.path.join(BASE_DIR, "statics"),) # 现添加的配置,这里是元组,注意逗号 TEMPLATES = [ ... 'DIRS': [os.path.join(BASE_DIR, 'templates')], ]
urls.py
from django.contrib import admin from django.urls import path from django.conf.urls import url, include from app01 import views urlpatterns = [ path('admin/', admin.site.urls), url(r'login.html/', views.Login), url(r'^login_ajax.html', views.login_ajax), ]
views.py
from django.shortcuts import render from django.shortcuts import HttpResponse import json def login_ajax(request): if request.method == "GET": return render(request, 'login_ajax.html') elif request.method == "POST": ret = {'status': True, 'error':None, 'data': None} obj = LoginForm(request.POST) if obj.is_valid(): print(obj.clean()) else: # 方式一 # res_str = obj.errors.as_json() # res_str是一个字符串 # ret['status'] = False # ret['error'] = res_str # 两次反序列化 # 方式二:将Django的ValidationError类型转换为JSON对象 ret['status'] = False ret['error'] = obj.errors.as_data() #Djaongo的数据类型 {'user': [ValidationError(['用户名长度不能小6'])], 'email': [ValidationError(['邮箱格式错误'])]} # 一次反序列化 return HttpResponse(json.dumps(ret, cls=JsonCustomEncoder)) # 方式一不需要此类 from django.core.validators import ValidationError class JsonCustomEncoder(json.JSONEncoder): def default(self, field): if isinstance(field, ValidationError): return {'code': field.code, 'message': field.message} else: return json.JSONEncoder.default(self, field)
templates/login_ajax.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> .error-msg{ color: red; font-size: 12px; } </style> </head> <body> <h1>Form提交数据</h1> <form id="f1"> <p> <input id="u" type="text" name="user" placeholder="用户名" /> </p> <p> <input id="e" type="text" name="email" placeholder="邮箱" /> </p> <p> <input id="p" type="text" name="pwd" placeholder="密码" /> </p> <input id="ajax_submit" type="button" value="Ajax提交" /> </form> <script src="/static/jquery-2.1.4.min.js"></script> <script> $(function () { $('#ajax_submit').click(function () { $.ajax({ url:"/login_ajax.html", //data: {user: $('#u').val(), email: $('#e').val(), pwd: $('#p').val()}, data: $('#f1').serialize(), type: 'POST', success:function (arg) { $('.error-msg').remove(); var v1 = JSON.parse(arg); //解析JSON数据 console.log(v1); if(!v1.status){ // var error_obj = JSON.parse(v1.error); var error_obj = v1.error; $.each(error_obj,function (k,v) { // k: user 或 email // v: [{}{}{},] var tag = document.createElement('span'); tag.className = 'error-msg'; tag.innerHTML = v[0].message; $("input[name='" + k +"']").after(tag); }) }else{ location.href = "/inde.html" } // { 'stauts': true, 'error':xx, 'data':’‘} } }) }) }) </script> </body> </html>
页面显示;
DjangoForm更多用法之多选框
settings.py
INSTALLED_APPS = [ ... 'app01', # 注册app ] STATICFILES_DIRS = (os.path.join(BASE_DIR, "statics"),) # 现添加的配置,这里是元组,注意逗号 TEMPLATES = [ ... 'DIRS': [os.path.join(BASE_DIR, 'templates')], ]
urls.py
from django.contrib import admin from django.urls import path from django.conf.urls import url, include from app01 import views urlpatterns = [ path('admin/', admin.site.urls), url(r'^index.html', views.index), url(r'^edit_index.html', views.edit_index), ]
views.py
from django.shortcuts import render from django.shortcuts import HttpResponse class IndexForm(forms.Form): # 模版中的元素 user = forms.CharField(min_length=6,error_messages={"required": '用户名不能为空','min_length': '用户名长度不能小6'}) email = forms.EmailField(error_messages={"required": '邮箱不能为空','invalid': '邮箱格式错误'}) favor = forms.MultipleChoiceField( choices=[(1,'AAA'),(2,'BBB'),(3,'CCC')] ) def index(request): obj = IndexForm() return render(request,'index.html',{'obj': obj}) def edit_index(request): obj = IndexForm({'user': 'root','email': 'hhh@666.com','favor': [2,3]}) return render(request,'index.html',{'obj': obj})
templates/index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <p>{{ obj.user }}</p> <p>{{ obj.email }}</p> <p>{{ obj.favor }}</p> </body> </html>
DjangoForm更多用法之widget插件基本使用
settings.py
INSTALLED_APPS = [ ... 'app01', # 注册app ] STATICFILES_DIRS = (os.path.join(BASE_DIR, "statics"),) # 现添加的配置,这里是元组,注意逗号 TEMPLATES = [ ... 'DIRS': [os.path.join(BASE_DIR, 'templates')], ]
urls.py
from django.contrib import admin from django.urls import path from django.conf.urls import url, include from app01 import views urlpatterns = [ # 带插件的Form url(r'^detail.html', views.Detail), ]
views.py
from django.shortcuts import render, redirect from django import forms # forms里面引用了field,widget的内容 from django.forms import fields # 这里再次引用是为了更加明确而已 from django.forms import widgets # 带插件的Form,这里是定义模板 class DetailForm(forms.Form): # user = fields.CharField() 默认widget = TextInput;此时就是一个白框,里面输入的文字都是明文【字符串】 # 自定义样式: attrs={'class': 'c1'} 此时就告诉Django,我要给生成的标签添加了样式class=c1 user = fields.CharField(widget=widgets.PasswordInput(attrs={'class': 'c1', 'placeholder': '请输入密码'})) # choices接收的是列表,列表里面是元组,里面2个值[第一个参数是value值,第二个是] choice = fields.ChoiceField(choices=[(1, '北京'), (2, '南京'), (3, '天津')]) # Django可以把前台的字符串转换为数字类型 age = fields.IntegerField() # 总结: 如果是个单值[字符串],直接获取用户输入的字符串, ---> CharField()[获取字符串] # 如果是个单值[数 字],直接获取用户输入的数字, ---> IntegerField(),Django帮我们字符串换Int类型 # 如果是个多值[下拉框],直接获取用户选择的字符串, ---> ChoiceField()[获取的是字符串] # 前台返回的只有3类:字符串,数字, 列表 def Detail(request): obj = DetailForm() return render(request, 'detail.html', {'obj': obj})
templates/detail.html、
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> </head> <body> {{ obj.user }} {{ obj.choice }} </body> </html>
页面显示;
学习拓展:
choice = fields.ChoiceField(choices=[(1, '北京'), (2, '南京'), (3, '天津')]) new_choice = fields.CharField(widget=widgets.Select(choices=[(1, '北京'), (2, '南京'), (3, '天津')])) int_choice = fields.IntegerField(widget=widgets.Select(choices=[(1, '北京'), (2, '南京'), (3, '天津')])) radio_select = fields.CharField(widget=widgets.RadioSelect(choices=[(1, '北京'), (2, '南京'), (3, '天津')]))
CharField也可以利用插件实现select的效果,所以ChoiceField实际上是new_choice一系列的简写
Choice和new_choice的返回结果是字符串
Int_choice的返回结果是整数类型
最强大的还是CharField,虽然生成的text文本框,但是可以通过插件实现转换其他HTML样式
DjangoForm更多用法之字段和插件更多使用
settings.py
INSTALLED_APPS = [ ... 'app01', # 注册app ] STATICFILES_DIRS = (os.path.join(BASE_DIR, "statics"),) # 现添加的配置,这里是元组,注意逗号 TEMPLATES = [ ... 'DIRS': [os.path.join(BASE_DIR, 'templates')], ]
urls.py
from django.contrib import admin from django.urls import path from django.conf.urls import url, include from app01 import views urlpatterns = [ # 带插件的Form url(r'^detail.html', views.Detail), url(r'^fieldForm.html', views.DetailField), ]
views.py
from django.shortcuts import render, redirect from django import forms # forms里面引用了field,widget的内容 from django.forms import fields # 这里再次引用是为了更加明确而已 from django.forms import widgets from django.core.validators import RegexValidator # 字段的详细使用 class FieldForm(forms.Form): f = fields.CharField( required=True, # 是否必须填写, 默认是必填的, max_length=8, # 最大长度限制 min_length=6, # 最小长度限制 label='用户名', # 用于前端显示用的标签 obj.f.label 自带属性; 也可用obj.f.label_tag实现自动写入 initial='用户名', # 文本框内的初始值; views里面注意区别GET和POST请求,initial默认是GET请求显示 show_hidden_initial='初始隐藏的值', # 显示一个隐藏的标签,可以判断输入的值和隐藏的值是否有区别,然后处理 validators=[RegexValidator(r'^[0-9]+$', 'phoneNumber must be digital', code='phoneNumberError'), ], # 自定义验证规则 error_messages={'required': '不能为空', 'invalid': '格式错误', 'max_length': '格式太长了'}, # 不指定则显示默认的 disabled=True, # 默认disabled=False,表示文本框可以编辑 label_suffix='--->', # label的后缀,默认是冒号,这里更改为 ---> ) ''' 注意: error_messages里面通过code来进行错误信息的匹配 想覆盖原来英文的错误信息,在error_messages覆盖即可 error_messages的优先级别高于自定义的优先级,且根据code来进行匹配 error_messages可以根据前面有什么参数[eg,min_length],message的code就可以写什么[这里就是min_length] 最常用的2个: required, invalid max_length min_length ''' # 另一种方式实现自定义正则[第一种是上述的CharField里面的的validator] f2 = fields.RegexField(r'^[0-9]+$') ''' 文件上传: 1.form表单需要使用enctype="multipart/form-data" 2.后台需要request.Files来接收文件, obj = FieldForm(request.POST, request.FILES) 3.获取文件对象InMemoryUploadedFile[对象内有文件名称,文件大小,文件内容] ''' f3 = fields.FileField(allow_empty_file=False) # 文件不允许为空 # 设置下拉框,此时默认返回的是字符串类型 f4 = fields.ChoiceField( initial=2, # 设置默认值,单选的时候只能选择1个默认值哈 choices=((1, 'AAA'), (2, 'BBB'), (3, 'CCC')), # 设置下拉选项[可迭代的就行]此时返回的1,2,3是字符串'1','2','3' ) # 自带类型转换的Choice f5 = fields.TypedChoiceField( coerce=lambda x: int(x), # 传递的参数转换为int类型; lambda的等号[=]2边不需要空格 initial=2, # 设置默认值,单选的时候只能选择1个默认值哈 choices=((1, 'AAA'), (2, 'BBB'), (3, 'CCC')), # 设置下拉选项[可迭代的就行]此时返回的1,2,3是字符串'1','2','3' ) # 设置下拉框多选 f6 = fields.MultipleChoiceField( initial=(2, 3), # 设置默认值,必须是可迭代的就行 choices=((1, 'AAA'), (2, 'BBB'), (3, 'CCC')), # 设置下拉选项[可迭代的就行]此时返回的1,2,3是字符串'1','2','3' ) # 实现多个验证[既满足A又满足B] f7 = fields.ComboField(fields=[fields.CharField(max_length=20), fields.EmailField(), ]) # 里面是个可迭代对象 # 抽象类,子类中可以实现聚合多个字典去匹配一个值,要配合MultiWidget使用 f8 = fields.MultiValueField(fields=[fields.ChoiceField(), ]) # 里面是可迭代对象 # 生成2个框,因为继承了MultiValueField[这个类中有2个定制的CharField] f9 = fields.SplitDateTimeField() # 文件选项:此时会把当前app01路径下的所有文件以下拉框的形式显示[提交也是提交选中选项] f10 = fields.FilePathField(path='app01', match=None, # 正则匹配 recursive=False, # 递归下面的文件夹 allow_files=True, # 是否允许文件 allow_folders=False, # 是否允许文件夹等其他属性) ) # IP的验证 f11 = fields.GenericIPAddressField() # 只允许数字,字母,下划线 f12 = fields.SlugField() # 数字,字母,下划线,减号(连字符) # UUID f13 = fields.UUIDField() def DetailField(request): if request.method == "GET": obj = FieldForm() return render(request, 'fieldForm.html', {'obj': obj}) else: obj = FieldForm(request.POST, request.FILES) # 注意别忘了参数,因为is_valid和clean都是POST请求的 obj.is_valid() data = obj.clean() error_json = obj.errors.as_json() print("正确信息:", data) print("错误信息:", error_json) return render(request, 'fieldForm.html', {'obj': obj})
templates/fieldForm.html、
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> </head> <body> <form action="/fieldForm.html/" method="post" enctype="multipart/form-data"> <h2>{{ obj.f.id_for_label }} 是个字符串,自动生成了一个id,这里自定制label效果</h2> <label for="{{ obj.f.id_for_label }}">{{ obj.f.label }}:</label>{{ obj.f }} <hr> <h2> {{ obj.f.label_tag }}可以自动帮我们生成label标签,等价上面的全部 </h2> {{ obj.f.label_tag }}{{ obj.f }}<hr> <h2>第二种自定义正则</h2> {{ obj.f2 }}<hr> <h2>文件上传</h2> {{ obj.f3 }}<hr> <h2>下拉框</h2> {{ obj.f4 }}<hr> <h2>多选下拉框</h2> {{ obj.f6 }} <input type="submit" value="提交"> </form> </body> </html>
页面显示[不全显示];
DjangoForm应用-- select数据从数据库取且实时刷新
settings.py
INSTALLED_APPS = [ ... 'app01', # 注册app ] STATICFILES_DIRS = (os.path.join(BASE_DIR, "statics"),) # 现添加的配置,这里是元组,注意逗号 TEMPLATES = [ ... 'DIRS': [os.path.join(BASE_DIR, 'templates')], ]
urls.py
from django.contrib import admin from django.urls import path from django.conf.urls import url, include from app01 import views urlpatterns = [ # select的数据从数据库来,且实时更新 url(r'^db.html', views.db), ]
views.py
from django.shortcuts import render, redirect from django import forms # forms里面引用了field,widget的内容 from django.forms import fields # 这里再次引用是为了更加明确而已 from django.forms import widgets from django.core.validators import RegexValidator from app01.models import DBModel class DBForm(forms.Form): d1 = fields.CharField() # 固定的option type1 = fields.ChoiceField(choices=[(1, 'AAA'), (2, 'BBB'), (3, 'CCC')]) # 从数据库内获取option type2 = fields.ChoiceField(choices=DBModel.objects.all().values_list()) # 将数据转换为元组类型的list # 实时刷新数据库内容 type3 = fields.ChoiceField(choices=[]) # 数据从数据库读取一次,每次生成对象都从内存获取,易产生脏数据 def __init__(self, *args, **kwargs): # 调用父级别的构造方式,每次创建对象的时候都会获取数据 super(DBForm, self).__init__(*args, **kwargs) self.fields['type3'].choices = DBModel.objects.all().values_list() # 数据从此处获取 def db(request): # 手动在数据库内创建数据库数据 --> 图形界面提交 if request.method == "GET": obj = DBForm() return render(request, 'db.html', {'obj': obj}) else: obj = DBForm(request.POST, request.FILES) # 注意别忘了参数,因为is_valid和clean都是POST请求 obj.is_valid() data = obj.clean() error_json = obj.errors.as_json() print("正确信息:", data) print("错误信息:", error_json) return render(request, 'db.html', {'obj': obj})
app01/models.py
from django.db import models # Create your models here. class DBModel(models.Model): type = models.CharField(max_length=22) # 创建type字段且id是Django帮我们创建
templates/db.html、
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> </head> <body> 用户名: {{ obj.d1 }}<br> 固定的: {{ obj.type1 }}<br> 数据库: {{ obj.type2 }}<br> 实时刷新数据库内容: {{ obj.type3 }}<br> </body> </html>
初始化数据库:
python manage.py makemigrations python manage.py migrate
页面显示[不全显示]
数据库内容:
DjangoForm应用--新URL方式编辑时,默认内容选中
settings.py
INSTALLED_APPS = [ ... 'app01', # 注册app ] STATICFILES_DIRS = (os.path.join(BASE_DIR, "statics"),) # 现添加的配置,这里是元组,注意逗号 TEMPLATES = [ ... 'DIRS': [os.path.join(BASE_DIR, 'templates')], ]
urls.py
from django.contrib import admin from django.urls import path from django.conf.urls import url, include from app01 import views urlpatterns = [ # 新URL方式编辑时,且内容默认选中 url(r'^dbEdit.html', views.dbEdit), ]
views.py
from django.shortcuts import render, redirect from django import forms # forms里面引用了field,widget的内容 from django.forms import fields # 这里再次引用是为了更加明确而已 from django.forms import widgets from django.core.validators import RegexValidator from app01 import models class DBEditForm(forms.Form): user = fields.CharField() user_type1 = fields.IntegerField(widget=widgets.Select(choices=[(1, 'AAA'), (2, 'BBB'), (3, 'CCC')])) user_type2 = fields.IntegerField(widget=widgets.Select(choices=[])) def __init__(self, *args, **kwargs): super(DBEditForm, self).__init__(*args, **kwargs) self.fields['user_type2'].widget.choices = DBModel.objects.all().values_list() # 新URL方式编辑时,默认选中 def dbEdit(request): if request.method == "GET": nid = request.GET.get('nid') # 前台定义的nid info = models.UserInfo.objects.filter(id=nid).first() print('用户姓名:', info.usename, '\n用户类型:', info.type_id) ''' 如果这里的字典dic跟DBEditForm里面的字段一致,则Django默认会帮我们填补数据的 方案一: 自定义固定的内容:这里采用自定义,info我们转换为字典同理同效果 dic = {'user': 'root2020', 'user_type1': 3, 'user_type2': 5} obj = DBEditForm(dic) 方案二: 将info对象转换为字典,根据前台的nid动态的获取内容 dic = {'user': 'root2020', 'user_type1': 3, 'user_type2': 5} 注意: 如果是多选的话,则只需要返回一个列表即可 dic = {'user': 'root2020', 'user_type1': 3, 'user_type2': 5, 'favor':[1,2,3,4]} ''' dic = {'user': info.usename, 'user_type1': 3, 'user_type2': info.type_id} # 根据前台的反馈来进行数据匹配 obj = DBEditForm(dic) return render(request, 'dbEdit.html', {'obj': obj}) else: obj = DBEditForm(request.POST, request.FILES) # 注意别忘了参数,因为is_valid和clean都是POST请求的 obj.is_valid() data = obj.clean() error_json = obj.errors.as_json() print("正确信息:", data) print("错误信息:", error_json) return render(request, 'dbEdit.html', {'obj': obj})
app01/models.py
from django.db import models # Create your models here. class DBModel(models.Model): type = models.CharField(max_length=22) # 创建type字段且id是Django帮我们创建 class UserInfo(models.Model): usename = models.CharField(max_length=22) # type在数据库内显示的值为: type_id type = models.ForeignKey("DBModel", on_delete=True) # 设置外键,一对多,这里是多的一方
templates/ dbEdit.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> </head> <body> {{ obj.user }}<br> {{ obj.user_type1 }}<br> {{ obj.user_type2 }}<br> </body> </html>
初始化数据库:
python manage.py makemigrations python manage.py migrate
页面显示
数据库内容
-------------------------------------------
个性签名: 所有的事情到最後都是好的,如果不好,那說明事情還沒有到最後~
本文版权归作者【小a玖拾柒】和【博客园】共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利!