Django中的Form表单
程序员文章站
2022-04-25 16:30:23
...
方式1:
from django.shortcuts import render,HttpResponse,redirect
from django.views import View
from django.core import serializers
import json
# Create your views here.
# class LoginView(View):
# def dispatch(self, request, *args, **kwargs):
# print('before')
# response = super(LoginView,self).dispatch(request,*args,**kwargs)
# print('after')
# return response
#
# def get(self,request,*args,**kwargs):
# print('GET')
# return render(request,'login.html')
#
# def post(self,request,*args,**kwargs):
# print('POST')
# user = request.POST.get('user')
# pwd = request.POST.get('pwd')
# if user == 'alex' and pwd == '123':
# request.session['username'] = user
# return redirect('/index/')
# else:
# return render(request,'login.html',{'msg':'登陆失败'})
#
# def auth(func):
# def inner(request,*args,**kwargs):
# user = request.session.get('username')
# if user:
# return func(request,*args,**kwargs)
# else:
# return redirect('/login/')
# return inner
#
#
# """
# 在Django的CBV里面引入装饰器需要用到固定的格式
# """
#
# from django.utils.decorators import method_decorator
#
# class IndexView(View):
# """
# 继承View的原因:要用到as_view等方法
# """
# @method_decorator(auth) #这里相当于一个总闸门
# def dispatch(self, request, *args, **kwargs):
# response = super(IndexView, self).dispatch(request, *args, **kwargs)
# return response
#
#
# # @method_decorator(auth) => 可以直接放在这里加
# def get(self,request,*args,**kwargs):
# return HttpResponse(request.session['username'])
from app01 import models
def users(request):
return render(request,'users.html')
def get_users(request):
"""
function:我们需要加上response指定标准
"""
response = {'status':True,'data':None,'msg':None}
try:
user_list = models.UserInfo.objects.values('id','username')
# user_list = list(user_list),如果正确,则将user_list的数值赋值给data
response['data'] = list(user_list)
except Exception as e:
response['status'] = False
response['msg'] = str(e)
data = json.dumps(response)
return HttpResponse(data)
from django.forms import Form
from django.forms import fields
from django.forms import widgets
class UserForm(Form):
#通过这个类可以帮我们生成相应的html标签
user = fields.CharField(required=True)
email = fields.EmailField(required=True)
user_type = fields.ChoiceField(choices=[(1,'上海'),(2,'北京',),(3,'广州')])
class AddUserView(View):
def get(self,request,*args,**kwargs):
form = UserForm()
return render(request,'add_user.html',{'form':form})
def post(self,request,*args,**kwargs):
form = UserForm(data=request.POST)
#将用户提交的数据和UserForm中定义的规则进行匹配
if form.is_valid():
# 如果用户提交的数据正确,则获取用户所有的数据
print(form.cleaned_data)
return redirect('/xxxx.html')
else:
#显示相应的错误信息
print(form.errors)
# 此时前端自动将错误信息给显示出来了
return render(request,'add_user.html',{"form":form})
前端页面:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>添加用户</h1>
<form method="POST" novalidate>
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="提交">
</form>
</body>
</html>
运行结果:
问题:form.as_p不能够定制,虽然通过form.as_p可以生成form中所有的html标签,但是不能够定制,也不能够样式渲染。
def as_p(self):
"Returns this form rendered as HTML <p>s."
return self._html_output(
normal_row='<p%(html_class_attr)s>%(label)s %(field)s%(help_text)s</p>',
error_row='%s',
row_ender='</p>',
help_text_html=' <span class="helptext">%s</span>',
errors_on_separate_row=True)
改进1:(后端不做任何的改进,仅仅前端做改进)
<body>
<h1>添加用户</h1>
<form method="POST" novalidate>
{% csrf_token %}
{# 用户自定制相应的内容,form.errors.user实际上包含了很多的错误信息 #}
<p>用户名:{{ form.user }}{{ form.errors.user }}</p>
<p>邮箱:{{ form.email }}{{ form.errors.email.0 }}</p>
<p>用户类型:{{ form.user_type }}{{ form.errors.user_type.0 }}</p>
<input type="submit" value="提交">
</form>
</body>
效果展示:
改进2:将错误的提示信息用中文显示出来。
后台:
from django.shortcuts import render,HttpResponse,redirect
from django.views import View
from django.core import serializers
import json
# Create your views here.
# class LoginView(View):
# def dispatch(self, request, *args, **kwargs):
# print('before')
# response = super(LoginView,self).dispatch(request,*args,**kwargs)
# print('after')
# return response
#
# def get(self,request,*args,**kwargs):
# print('GET')
# return render(request,'login.html')
#
# def post(self,request,*args,**kwargs):
# print('POST')
# user = request.POST.get('user')
# pwd = request.POST.get('pwd')
# if user == 'alex' and pwd == '123':
# request.session['username'] = user
# return redirect('/index/')
# else:
# return render(request,'login.html',{'msg':'登陆失败'})
#
# def auth(func):
# def inner(request,*args,**kwargs):
# user = request.session.get('username')
# if user:
# return func(request,*args,**kwargs)
# else:
# return redirect('/login/')
# return inner
#
#
# """
# 在Django的CBV里面引入装饰器需要用到固定的格式
# """
#
# from django.utils.decorators import method_decorator
#
# class IndexView(View):
# """
# 继承View的原因:要用到as_view等方法
# """
# @method_decorator(auth) #这里相当于一个总闸门
# def dispatch(self, request, *args, **kwargs):
# response = super(IndexView, self).dispatch(request, *args, **kwargs)
# return response
#
#
# # @method_decorator(auth) => 可以直接放在这里加
# def get(self,request,*args,**kwargs):
# return HttpResponse(request.session['username'])
from app01 import models
def users(request):
return render(request,'users.html')
def get_users(request):
"""
function:我们需要加上response指定标准
"""
response = {'status':True,'data':None,'msg':None}
try:
user_list = models.UserInfo.objects.values('id','username')
# user_list = list(user_list),如果正确,则将user_list的数值赋值给data
response['data'] = list(user_list)
except Exception as e:
response['status'] = False
response['msg'] = str(e)
data = json.dumps(response)
return HttpResponse(data)
from django.forms import Form
from django.forms import fields
from django.forms import widgets
class UserForm(Form):
#通过这个类可以帮我们生成相应的html标签
user = fields.CharField(
required=True,
#自定义错误信息
error_messages={'required':'用户名不能为空'}
)
email = fields.EmailField(
required=True,
#自定义错误信息
error_messages={'required':'邮箱不能为空','invalid':'邮箱格式错误'}
)
ip = fields.GenericIPAddressField(
required=True,
# 自定义错误信息
error_messages={'required': 'IP不能为空', 'invalid': 'IP格式错误'}
)
user_type = fields.ChoiceField(choices=[(1,'上海'),(2,'北京',),(3,'广州')])
class AddUserView(View):
def get(self,request,*args,**kwargs):
#创建的类对象自动具有user、email和user_type三个属性
form = UserForm()
return render(request,'add_user.html',{'form':form})
def post(self,request,*args,**kwargs):
form = UserForm(data=request.POST)
#将用户提交的数据和UserForm中定义的规则进行匹配
if form.is_valid():
# 如果用户提交的数据正确,则获取用户所有的数据
print(form.cleaned_data)
#{'user': 'fds', 'user_type': '1', 'email': 'aaa@qq.com', 'ip': '192.168.80.100'}
return redirect('/xxxx.html')
else:
#显示相应的错误信息
print(form.errors)
# 此时前端自动将错误信息给显示出来了
return render(request,'add_user.html',{"form":form})
前端:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>添加用户</h1>
<form method="POST" novalidate>
{% csrf_token %}
{# 用户自定制相应的内容,form.errors.user实际上包含了很多的错误信息 #}
<p>用户名:{{ form.user }}{{ form.errors.user }}</p>
<p>邮箱:{{ form.email }}{{ form.errors.email.0 }}</p>
<p>IP:{{ form.ip }}{{ form.errors.ip.0 }}</p>
<p>用户类型:{{ form.user_type }}{{ form.errors.user_type.0 }}</p>
<input type="submit" value="提交">
</form>
</body>
</html>
效果展示:
到现在为止,我们在加入一个编辑的功能:
但是到现在为止还是有一个bug,这个bug就是当我的用户类型增加之后,在添加当中还是只显示以前的两个类型,只有通过重启之后才可以看到最新的类型:
解决方法:
class UserForm(Form):
def __init__(self,*args,**kwargs):
super(UserForm,self).__init__(*args,**kwargs)
self.fields['ut_id'].choices = \
models.UserType.objects.values_list('id','title')
#通过这个类可以帮我们生成相应的html标签
#字段名应该和数据库的名字一致
#静态字段加载的时候只有在第一次才会执行
username = fields.CharField(
required=True,
#自定义错误信息
error_messages={'required':'用户名不能为空'}
)
password = fields.EmailField(
required=True,
#自定义错误信息
error_messages={'required':'密码不能为空','invalid':'密码格式错误'}
)
# user_type = fields.ChoiceField(choices=[(1,'上海'),(2,'北京',),(3,'广州')])
ut_id = fields.ChoiceField(choices=models.UserType.objects.values_list('id','title'))
总结:4个步骤1个问题
总结:
1. 创建Form类(本质就是正则表达式的集合)
2. 只是生成HTML标签: 添加页面
form = MyForm()
{{form.xx}}
3. 带默认值的HTML标签: 编辑页面
form = MyForm(initial={'xx': xxx})
{{form.xx}}
4. 提交数据
form = MyForm(data=request.POST)
if form.is_valid():
print(form.cleaned_data)
else:
print(form.errors)
问题:下拉框数据无法实时更新
class UserForm(Form):
username = fields.CharField(
required=True,
error_messages={'required':'用户名不能为空'}
)
password = fields.CharField(
required=True,
error_messages={'required': '邮箱不能为空','invalid':'邮箱格式错误'}
)
ut_id = fields.ChoiceField(choices=[])
def __init__(self,*args,**kwargs):
super(UserForm,self).__init__(*args,**kwargs)
self.fields['ut_id'].choices = models.UserType.objects.values_list('id','title')
到现在为止,我们可以进行一对一,一对多的操作了,我们此时如何进行input的定制操作呢?
下面是不能进行class等修饰的
<form method="POST" novalidate>
{% csrf_token %}
{# 编辑的时候应该有默认值 #}
<p>用户名:{{ form.username }}{{ form.errors.username.0 }}</p>
<p>邮箱:{{ form.password }}{{ form.errors.password.0 }}</p>
<p>用户类型:{{ form.ut_id }}{{ form.errors.ut_id.0 }}</p>
<p>用户角色:{{ form.role_id }}{{ form.errors.role_id.0 }}</p>
<input type="submit" value="提交">
</form>
通过下面我们就可以将form表单嵌套在bootStrap当中:
class UserForm(Form):
def __init__(self,*args,**kwargs):
super(UserForm,self).__init__(*args,**kwargs)
self.fields['ut_id'].choices = \
models.UserType.objects.values_list('id','title')
self.fields['role_id'].choices =\
models.Role.objects.values_list('id','caption')
#通过这个类可以帮我们生成相应的html标签
#字段名应该和数据库的名字一致
#静态字段加载的时候只有在第一次才会执行
username = fields.CharField(
required=True,
#自定义错误信息
error_messages={'required':'用户名不能为空'},
widget=widgets.TextInput(attrs={'class':'form-control'})
)
password = fields.EmailField(
required=True,
#自定义错误信息
error_messages={'required':'密码不能为空','invalid':'密码格式错误'},
widget = widgets.Textarea(attrs={'class': 'form-control'})
)
# fields.EmailField()
# fields.GenericIPAddressField(protocol='ipv4')
# user_type = fields.ChoiceField(choices=[(1,'上海'),(2,'北京',),(3,'广州')])
ut_id = fields.ChoiceField(
choices=[],
widget=widgets.Select(attrs={'class':'form-control'})
)
role_id = fields.MultipleChoiceField(
choices=[],
widget=widgets.SelectMultiple(attrs={'class': 'form-control'})
)
综上我们的Form表单实际上有很多的功能,但是下面我们只使用Form表单验证的功能。
示例:只用表单验证的功能(Ajax提交)