多对多三种创建方式
1.全自动(一般情况下)
好处:
自始至终都没有操作第三种表,全部都是由orm自动创建的。
还内置了四个操作第三张表的方法。
不足:
自动创建的第三张表无法扩展修改字段,表的扩展性较差。
class Book(models.Model):
title=models.CharField(max_length=32)
#多对多关系字段
author=models.ManyToManyField(to='Author')
class Author(models.Model):
name=models.CharField(32)
2.纯手撸(了解)
好处:
第三张表字段个数和字段名称全都可以自己定义
不足:
不再支持orm跨表查询(add,remove,set,clear),不再有正反向的概念
class Book(models.Model):
title=models.CharField(max_length=32)
class Author(models.Model):
name=models.CharField(32)
class Book2Author(models.Model):
book=models.ForeignKey(to='Book')
author=models.ForeignKey(to='Author')
create_time=models.DateField(auto_now_add=True)
3.半自动(推荐使用)
好处:
可以任意的添加和修改第三张表中的字段,并且支持orm跨表查询
不足:
不支持内置的四个方法(add,remove,set,clear)
class Book(models.Model):
title=models.CharField(max_length=32)
#多对多关系字段
author=models.ManyToManyField(to='Author',through='Book2Author',through_fields=('book','author'))
'''through_fields:在那张表中,那个字段就放在前面
当你的ManyToManyField只有一个参数to的情况下,orm会自动创建第三张表
如果加入了through和through_fields那么orm就不会自动帮你创建第三张表,
但是他会在内部维持关系,可以继续使用跨表查询,
through 自己指定第三张关系表
through_fields 自己指定第三张关系表 到底哪两个字段维护着表与表之间的多对多关系,'''
class Author(models.Model):
name=models.CharField(32)
class Book2Author(models.Model):
book=models.ForeignKey(to='Book')
author=models.ForeignKey(to='Author')
create_time=models.DateField(auto_now_add=True)
#该表中可以有任意多的外键字段,可以扩展任意的字段
forms校验性组件
需求:
1.写一个注册页面,获取用户输入的用户名和密码提交到后端之后,后端需要对用户名和密码做校验。不符合的展示对应的错误信息。
将数据传递给后端做数据校验 》》》检验数据
手动书写html代码获取用户输入》》》渲染标签
如果数据错误,展示错误信息 》》》展示信息
forms组件:
能够做的事情就是上面的三步
渲染标签 检验数据 展示信息
使用forms组件的前提是:提前写好一个类
# 使用forms组件的第一步,必须先写一个类
from django import forms
class MyForm(forms.Form):
# username字段 最少三位 最多八位
username = forms.CharField(max_length=8, min_length=3)
# password字段 最少三位 最多八位
password = forms.CharField(max_length=8, min_length=3)
# email字段 必须是邮箱格式
email=forms.EmailField()
校验数据
# 点击python console
from app02 import views
#1.给写好的类传字典数据(待校验的数据)
form_obj=views.MyForm({'username':'jason','password':'12','email':'123'})
#2.如何查看校验的数据是否合法
form_obj.is_valid()
Out[4]: False # 只有数据全部符合校验规则的情况下,结果才是True,否则都为False
#3.如何查看不符合规则的字段及错误的理由
form_obj.errors
Out[5]:
{'password': ['Ensure this value has at least 3 characters (it has 2).'],
'email': ['Enter a valid email address.']}
# 4.如何查看符合校验规则的数据
form_obj.cleaned_data
Out[6]: {'username': 'jason'}
# 5.forms组件中,定义的字段默认都是必须要传值的,不能少传
form_obj=views.MyForm({'username':'jason','password':'123'})
form_obj.is_valid()
Out[8]: False
form_obj.errors
Out[10]: {'email': ['This field is required.']}
# 6.forms组件只会校验forms类中定义的字段,如果多传了,不会有任何影响
form_obj=views.MyForm({'username':'jason','password':'1234','email':'[email protected]','xxx':'jjkj'})
form_obj.is_valid()
Out[13]: True
渲染标签
forms组件只会帮你渲染获取用户输入的标签,不会帮你渲染提交按钮,需要手动添加
视图层:
def indexx(request):
#渲染标签 第一步 需要生成一个空的forms类的对象
form_obj=MyForm()
#直接将生成得对象,传递给前端页面
return render(request,'indexx.html',locals())
前端:
<p>forms组件渲染标签方式一:封装程度太高,不推荐使用,但是可以用在本地测试</p>
{{ form_obj.as_p }}
{{ form_obj.as_ul }}
{{ form_obj.as_table }}
<p>forms组件渲染标签方式二:不推荐使用,写起来太麻烦</p>
{{ form_obj.username.label }}{{ form_obj.username }}
{{ form_obj.password.label }}{{ form_obj.password }}
{{ form_obj.email.label }}{{ form_obj.email }}
<p>forms组件渲染标签方式三:推荐使用</p>
{% for forms in form_obj %}
<p>
{{ forms.label }}{{ forms }}
</p>
{% endfor %}
如何将lable该成中文:在定义类得时候,给每个字段添加lable属性
class MyForm(forms.Form):
# username字段 最少三位 最多八位
username = forms.CharField(max_length=8, min_length=3,label='用户名')
# password字段 最少三位 最多八位
password = forms.CharField(max_length=8, min_length=3,label='密码')
# email字段 必须是邮箱格式
email=forms.EmailField(label='邮箱')
展示信息
数据的校验通常前后端都必须有,但前端的校验可有可无,并且弱不禁风。后端的校验必须要有,并且必须非常的全面。
如何告诉浏览器不做校验,form表单中加一个novalidate参数即可
如何报错信息为中文,在MyForm类里字段里加error_message属性
视图层:
from django import forms
class MyForm(forms.Form):
# username字段 最少三位 最多八位
username = forms.CharField(max_length=8, min_length=3,label='用户名',
error_messages={
'max_length':'用户名最长为八位',
'min_length':'用户名最短为三位',
'required':'用户名不能为空'
})
# password字段 最少三位 最多八位
password = forms.CharField(max_length=8, min_length=3,label='密码',
error_messages={
'max_length': '用户名最长为八位',
'min_length': '用户名最短为三位',
'required': '用户名不能为空'
})
# email字段 必须是邮箱格式
email=forms.EmailField(label='邮箱',
error_messages={
'required':'邮箱不能为空',
'invalid':'邮箱格式错误'
})
def indexx(request):
#渲染标签 第一步 需要生成一个空的forms类的对象
form_obj=MyForm()
if request.method=='POST':
#获取用户得数据 request.POST中 forms组件校验数据
form_obj=MyForm(request.POST)#该变量名一定要跟上面的form_obj变量名一致
if form_obj.is_valid():#研就forms组件入口就是
print(form_obj.cleaned_data)
return HttpResponse('数据全部OK')
else:
print(form_obj.errors)
#直接将生成得对象,传递给前端页面
return render(request,'indexx.html',locals())
前端:
<p>forms组件渲染标签方式三:推荐使用</p>
<form action="" method="post" novalidate>
{% for forms in form_obj %}
<p>
{{ forms.label }}{{ forms }}
<span>{{ forms.errors.0 }}</span>
</p><!--form等价与方式二中对象点字段名-->
{% endfor %}
<input type="submit">
</form>
</body>
</html>
校验数据的方式:
内置的校验器
在MyForm类里字段里加validators属性
from django.core.validators import RegexValidator
validators=[
RegexValidator(r'^[0-9]+$','请输入数字'),
RegexValidator(r'^159[0-9]+$','数字必须以159开头')
]
钩子函数 HOOK
当你觉得上面的所有的校验还是不能满足你的需求,你可以考虑使用钩子函数
是一个函数,函数体内你可以写任意的校验代码。在MyForm类里写
局部钩子
校验单个字段
def clean_username(self):
username=self.cleaned_data.get('username')
if '666' in username:
#给username所对应的框展示错误信息
self.add_error('username','光喊666是不行的')
return username
全局钩子
校验多个字段
def clean(self):
password=self.cleaned_data.get('password')
confirm_password=self.cleaned_data.get('confirm_password')
if not password==confirm_password:
self.add_error('confirm_password','两次密码不一致')
return self.cleaned_data
其他字段及参数
lable input框对应的提示信息
initial inout框默认值
required 默认为True控制字段是否必填
username = forms.CharField(max_length=8, min_length=3,label='用户名',initial='jason',required=False,
error_messages={
'max_length':'用户名最长为八位',
'min_length':'用户名最短为三位',
'required':'用户名不能为空'
})
widget 给input框设置样式及属性 在MyForm类里字段里加widget属性
from django.forms import widgets
widget=forms.widgets.TextInput({'class':'form-control c1 c2','username':'jason'})#添加了属性
widget=forms.widgets.PasswordInput()#input框变成了密文框