form组件
1 生成html标签
2 保留原来的数据
3 校验用户提交的数据
如何给生成的标签加样式
利用Form自动生成HTML标签
第1步 在views.py文件中 导入from django import forms模块 定义一个类 继承与forms.Form 名字随意 继承forms.Form
第2步 修改forms.后面的 变更不同属性
第3步 修改forms.widgets.后面的 变更不同标签
第4步 实列化这个类 传给后端
第5步 写后端代码
{{对象.字段.label }}就是自定义名字
{{ 对象.字段 }} 就会生成标签
{{ 对象.字段.errors.0 }}就会生成错误信息 第1个
from django import forms
#生成用户名输入框 name对应username vluse对应用户输入的值
class UserInfo(forms.Form):
username=forms.CharField(
label='用户名:',
initial="张三",#默认值
widget=forms.widgets.TextInput,
)
#生成密码输入框 name对应password vluse对应用户输入的值
password=forms.CharField(
label='密码:',
widget=forms.widgets.PasswordInput(attrs={'class':'c1'}),---attrs里面可以添加属性
)
#生成单选框 默认下拉框 name对应 sex vluse对应用户选择的值
sex = forms.ChoiceField(
choices=((1,'女'),(2,'男'),),#元祖套列表或元祖套元祖
# widget=forms.RadioSelect,----修改成这样变成小圆点选择框
# widget=forms.widgets.Select,---这是下拉框 默认就是
)
#生成多选框 默认下拉框 name对应 hobby vluse对应用户选择的值
hobby = forms.MultipleChoiceField(
choices= ((1,'喝酒'),(2,'抽烟'),(3,'烫头')),
# widget=forms.SelectMultiple,---这是下拉框 默认就是
widget=forms.CheckboxSelectMultiple,---修改成小方块选择框
)
#生成 选中框 name对应 remember_me
remember_me = forms.ChoiceField(
label='记住我',
widget=forms.CheckboxInput,
)
#生成 日期选择框 name对应 bday
bday = forms.DateField(
label='出生日期',
# 日期类型必须加上日期属性
widget=forms.DateInput(attrs={'type':'date'}),
)
def index(request):
if request.method == 'GET':
u_obj = UserInfo()#实列化对象
return render(request,'index.html',{'u_obj':u_obj})
else:
u_obj = UserInfo(request.POST) #用户提交的数据给类 进行实例化
if u_obj.is_valid():#效验用户数据
# {'username': 'a范德萨水电费', 'password': '1111'}
print('正确数据',u_obj.cleaned_data) #校验成功之后的数据cleaned_data
return HttpResponse('ok')
else:
# print('错误信息',u_obj.errors)
return render(request,'index.html',{'u_obj':u_obj})
前端模板写法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
.c1{
background-color: red;
}
</style>
</head>
<body>
<h1>某某登录页面</h1>
{#{{ u_obj.errors }}#}全部报错信息
<form action="" method="post" novalidate>
{% csrf_token %} 安全验证
{# 用户名: <input type="text" name="username">#}
{# 密码: <input type="password" name="password">#}
{{ u_obj.username.label }} {{ u_obj.username }} {{ u_obj.username.errors.0 }}
</div>
<div>
{{ u_obj.password.label }} {{ u_obj.password }} {{ u_obj.password.errors.0 }}
</div>
<div>
{{ u_obj.r_password.label }} {{ u_obj.r_password }} {{ u_obj.r_password.errors.0 }}
</div>
<input type="submit">
</form>
利用form保留原来的数据
默认自动保留
password不会自动保留数据在widget里面添加render_value=True就可以强制留下
r_password = forms.CharField(
label='确认密码:',
widget=forms.widgets.PasswordInput(attrs={'class': 'c1'}, render_value=True),
)
render_value=True强制留
利用form校验用户提交的数据
简单效验用户数据
u_obj.password.errors.0 获得第一个错误数据
常见属性
min_length设置用户输入长度最小值
max_length设置用户输入长度最大值
required=True, #不允许输入为空,值为False就可以为空
自定义错误信息后就不会显示英文的了
error_messages={
'required':'不能为空',
'min_length':'太短了!',
'max_length':'太长了!',
},
注意浏览器会自动帮你效验 要想浏览器不效验 在前端代码设置(novalidate)提示浏览器不要多管闲事
<form action="" method="post" novalidate>
下面的代码实列
username=forms.CharField(
label='用户名:',
# initial='张三' #默认值
# min_length=6, #最小值为6位
# required=True, #不允许为空,值为False就可以为空
# widget=forms.widgets.TextInput,
# max_length=8,
error_messages={
'required':'不能为空',
'min_length':'太短了!',
'max_length':'太长了!',
},
validators=[RegexValidator(r'^a','必须以a开头!'),RegexValidator(r'b$','必须以b结尾!')]
# validators=[mobile_validate,] #a范德萨水电费
)
正则校验器RegexValidator验证器
第一步引入模块from django.core.validators import RegexValidator
第2步定义规则 可以定义多个规则
validators=[RegexValidator(r'^a','必须以a开头!'),RegexValidator(r'b$','必须以b结尾!')] 第一个参数是正则 第2个参数是错误信息
下面是代码实列
username=forms.CharField(
label='用户名:',
initial='张三' #默认值
min_length=6, #最小值为6位
required=True, #不允许为空,值为False就可以为空
widget=forms.widgets.TextInput,
max_length=8,
error_messages={
'required':'不能为空',
'min_length':'太短了!',
'max_length':'太长了!',
},
validators=[RegexValidator(r'^a','必须以a开头!'),RegexValidator(r'b$','必须以b结尾!')]
自定义验证规则
当正则效验 与基础效验 满足不了 我们就需要 自定义验证规则了( )
第1步引入模块
from django.core.exceptions import ValidationError
import re
第2步定义一个函数
函数里面value是形参 传要验证的字符串
mobile_re是利用re模块编译出来的正则规则
利用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('手机号码格式错误')
第3步 在类里面 验证类里面加入·
validators=[定义的函数名,]
代码实列
from django.core.validators import RegexValidator
from django.core.exceptions import ValidationError
import re
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 UserInfo(forms.Form):
username=forms.CharField(
label='用户名:',
# initial='张三' #默认值
# min_length=6, #最小值为6位
# required=True, #不允许为空,值为False就可以为空
# widget=forms.widgets.TextInput,
# max_length=8,
error_messages={
'required':'不能为空',
'min_length':'太短了!',
'max_length':'太长了!',
},
validators=[RegexValidator(r'^a','必须以a开头!'),RegexValidator(r'b$','必须以b结尾!')]
validators=[mobile_validate,] #a范德萨水电费
)
password=forms.CharField(
label='密码:',
widget=forms.widgets.PasswordInput(attrs={'class':'c1'},render_value=True),
)
r_password = forms.CharField(
label='确认密码:',
widget=forms.widgets.PasswordInput(attrs={'class': 'c1'}, render_value=True),
)
# 局部钩子
def clean_username(self):
value = self.cleaned_data.get('username')
if '666' in value:
raise ValidationError('光喊666是不行的!')
else:
return value
# 全局钩子
def clean(self):
password = self.cleaned_data.get('password')
r_password = self.cleaned_data.get('r_password')
if password == r_password:
return self.cleaned_data
else:
# raise ValidationError('两次密码不一致!!!!')
self.add_error('r_password','两次密码不一致~~~~') # 给单独的某个字段加错误信息
def index(request):
if request.method == 'GET':
u_obj = UserInfo()
return render(request,'index.html',{'u_obj':u_obj})
else:
效验
u_obj = UserInfo(request.POST) #{'username':'','password':'123'}
print(u_obj.fields)
# u_obj.is_valid() #校验用户提交的数据,全部校验成功返回True,任意一个失败都返回False
if u_obj.is_valid():
# {'username': 'a范德萨水电费', 'password': '1111'}
print('正确数据',u_obj.cleaned_data) #校验成功之后的数据cleaned_data
return HttpResponse('ok')
else:
# print('错误信息',u_obj.errors)
return render(request,'index.html',{'u_obj':u_obj})
Hook钩子方法
局部钩子
第1步 我们在Fom类中定义 clean_字段() 方法,就能够实现对特定字段进行校验。
注意事项
效验顺序是先效验字段里面的效验规则 然后在效验局部钩子 最后下一字段
实列写法(cleaned_data是效验以后得到的数据)
def clean_username(self):
value = self.cleaned_data.get('username')
if '666' in value:
raise ValidationError('光喊666是不行的!')--错误信息
else:
return value--一定要返回不然会吧username对应的value剔除
钩子是写在类里面
代码实列
from django.core.validators import RegexValidator
from django.core.exceptions import ValidationError
import re
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 UserInfo(forms.Form):
username=forms.CharField(
label='用户名:',
# initial='张三' #默认值
# min_length=6, #最小值为6位
# required=True, #不允许为空,值为False就可以为空
# widget=forms.widgets.TextInput,
# max_length=8,
error_messages={
'required':'不能为空',
'min_length':'太短了!',
'max_length':'太长了!',
},
validators=[RegexValidator(r'^a','必须以a开头!'),RegexValidator(r'b$','必须以b结尾!')]
validators=[mobile_validate,] #a范德萨水电费
)
password=forms.CharField(
label='密码:',
widget=forms.widgets.PasswordInput(attrs={'class':'c1'},render_value=True),
)
r_password = forms.CharField(
label='确认密码:',
widget=forms.widgets.PasswordInput(attrs={'class': 'c1'}, render_value=True),
)
# 局部钩子
def clean_username(self):
value = self.cleaned_data.get('username')
if '666' in value:
raise ValidationError('光喊666是不行的!')
else:
return value
# 全局钩子
def clean(self):
password = self.cleaned_data.get('password')
r_password = self.cleaned_data.get('r_password')
if password == r_password:
return self.cleaned_data
else:
# raise ValidationError('两次密码不一致!!!!')
self.add_error('r_password','两次密码不一致~~~~') # 给单独的某个字段加错误信息
def index(request):
if request.method == 'GET':
u_obj = UserInfo()
return render(request,'index.html',{'u_obj':u_obj})
else:
效验
u_obj = UserInfo(request.POST) #{'username':'','password':'123'}
print(u_obj.fields)
# u_obj.is_valid() #校验用户提交的数据,全部校验成功返回True,任意一个失败都返回False
if u_obj.is_valid():
# {'username': 'a范德萨水电费', 'password': '1111'}
print('正确数据',u_obj.cleaned_data) #校验成功之后的数据cleaned_data
return HttpResponse('ok')
else:
# print('错误信息',u_obj.errors)
return render(request,'index.html',{'u_obj':u_obj})
全局钩子
句部钩子全部指行完 在执行全局 比如多个字段对比效验, 比如确认密码
函数名固定写法
def clean(self):
password = self.cleaned_data.get('password')
r_password = self.cleaned_data.get('r_password')
if password == r_password:#效验成功了L
return self.cleaned_data---固定写法 cleaned_data源码里有
else:
# raise ValidationError('两次密码不一致!!!!')不用因为给全局了
self.add_error('r_password','两次密码不一致~~~~') # 给单独的某个字段加错误信息
代码实列
from django.core.validators import RegexValidator
from django.core.exceptions import ValidationError
import re
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 UserInfo(forms.Form):
username=forms.CharField(
label='用户名:',
# initial='张三' #默认值
# min_length=6, #最小值为6位
# required=True, #不允许为空,值为False就可以为空
# widget=forms.widgets.TextInput,
# max_length=8,
error_messages={
'required':'不能为空',
'min_length':'太短了!',
'max_length':'太长了!',
},
validators=[RegexValidator(r'^a','必须以a开头!'),RegexValidator(r'b$','必须以b结尾!')]
validators=[mobile_validate,] #a范德萨水电费
)
password=forms.CharField(
label='密码:',
widget=forms.widgets.PasswordInput(attrs={'class':'c1'},render_value=True),
)
r_password = forms.CharField(
label='确认密码:',
widget=forms.widgets.PasswordInput(attrs={'class': 'c1'}, render_value=True),
)
# 局部钩子
def clean_username(self):
value = self.cleaned_data.get('username')
if '666' in value:
raise ValidationError('光喊666是不行的!')
else:
return value
# 全局钩子
def clean(self):
password = self.cleaned_data.get('password')
r_password = self.cleaned_data.get('r_password')
if password == r_password:
return self.cleaned_data
else:
# raise ValidationError('两次密码不一致!!!!')
self.add_error('r_password','两次密码不一致~~~~') # 给单独的某个字段加错误信息
def index(request):
if request.method == 'GET':
u_obj = UserInfo()
return render(request,'index.html',{'u_obj':u_obj})
else:
效验
u_obj = UserInfo(request.POST) #{'username':'','password':'123'}
print(u_obj.fields)
# u_obj.is_valid() #校验用户提交的数据,全部校验成功返回True,任意一个失败都返回False
if u_obj.is_valid():
# {'username': 'a范德萨水电费', 'password': '1111'}
print('正确数据',u_obj.cleaned_data) #校验成功之后的数据cleaned_data
return HttpResponse('ok')
else:
# print('错误信息',u_obj.errors)
return render(request,'index.html',{'u_obj':u_obj})
利用from实现页面
# 批量添加属性样式
def __init__(self,*args,**kwargs):
super().__init__(*args,**kwargs)
for field_name,field in self.fields.items(): #orderdict(('username',charfield对象))
field.widget.attrs.update({'class':'form-control'})
modelform组件
class BookModelForm(forms.ModelForm):
# 优先级高
# title = forms.CharField(
# label='书名2',
# )
class Meta:
model = models.Book
#fields='__all__'
fields=['title','publishs']
labels={
'title':'书名',
'price':'价格',
'publishDate':'出版日期',
'publishs':'出版社',
'authors':'作者',
}
widgets={
'publishDate':forms.TextInput(attrs={'type':'date'}),
# 'publishDate2':forms.TextInput(attrs={'type':'date'}),
}
error_messages={
'title':{'required':'书名不能为空!',},
'price':{'required':'不能为空!',},
'publishDate':{'required':'不能为空!',},
'publishs':{'required':'不能为空!',},
'authors':{'required':'不能为空!',},
}
#
# def clean_title(self):
# pass
# def clean(self):
# pass
def __init__(self,*args,**kwargs):
super().__init__(*args,**kwargs)
for field_name,field in self.fields.items():
field.widget.attrs.update({'class':'form-control'})
为什么要有modelform组件
举个例子,你也许会有个Book 模型,并且你还想创建一个form表单用来添加和编辑书籍信息到这个模型中。 在这种情况下,在form表单中定义字段将是冗余的,因为我们已经在模型中定义了那些字段。
基于这个原因,Django 提供一个辅助类来让我们可以从Django 的模型创建Form,这就是ModelForm。
form与model的终极结合,会根据你model中的字段转换成对应的form字段,并且并你生成标签等操作。
modelform组件怎么用
第一步定义一个类 名字随便取 最好有含义 列入BookModelForm
类里面定义
class Meta:
model = models.Book
#fields='__all__' 拿到所有字段 生成from字段
class BookModelForm(forms.ModelForm):#类目随便取
# 优先级高
# title = forms.CharField(
# label='书名2',
# )
class Meta:
model = models.Book#找到book表
fields='__all__' #拿到所有字段 生成from字段
#fields=['title','publishs']
labels={
'title':'书名',
'price':'价格',
'publishDate':'出版日期',
'publishs':'出版社',
'authors':'作者',
}
widgets={
'publishDate':forms.TextInput(attrs={'type':'date'}),
# 'publishDate2':forms.TextInput(attrs={'type':'date'}),
}
error_messages={
'title':{'required':'书名不能为空!',},
'price':{'required':'不能为空!',},
'publishDate':{'required':'不能为空!',},
'publishs':{'required':'不能为空!',},
'authors':{'required':'不能为空!',},
}
#
# def clean_title(self): 钩子
# pass
# def clean(self):
# pass
def __init__(self,*args,**kwargs):#还是和from一样给所有字段添加样式
super().__init__(*args,**kwargs)
for field_name,field in self.fields.items():
field.widget.attrs.update({'class':'form-control'})
同源和跨域
同源机制:域名、协议、端口号相同的同源
简单请求
(1) 请求方法是以下三种方法之一:(也就是说如果你的请求方法是什么put、delete等肯定是非简单请求)
HEAD
GET
POST
(2)HTTP的头信息不超出以下几种字段:(如果比这些请求头多,那么一定是非简单请求)
Accept
Accept-Language
Content-Language
Last-Event-ID
Content-Type:只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain,也就是说,如果你发送的application/json格式的数据,那么肯定是非简单请求,vue的axios默认的请求体信息格式是json的,ajax默认是urlencoded的。
#vue.js axios -- $.ajax
支持跨域,简单请求
服务器设置响应头:Access-Control-Allow-Origin = '域名' 或 '*'
支持跨域,复杂请求
由于复杂请求时,首先会发送“预检”请求,如果“预检”成功,则发送真实数据。
“预检”请求时,允许请求方式则需服务器设置响应头:Access-Control-Request-Method
“预检”请求时,允许请求头则需服务器设置响应头:Access-Control-Request-Headers
res['Access-Control-Allow-Origin'] = 'http://127.0.0.1:8001'
res['Access-Control-Allow-Headers'] = 'content-type' 所有的content-type
# res['Access-Control-Allow-Methods'] = 'PUT'
# res['Access-Control-Allow-Origin'] = '*'
原文地址:https://www.cnblogs.com/saoqiang/p/12397718.html
时间: 2024-11-09 06:19:34