多对多三种创建方式
1.全自动(一般情况)
class Book(models.Model):
title = models.CharField(max_length=32) # 多对多关系字段
authors = models.ManyToManyField(to='Authors')
class Authors(models.Model):
name = models.CharField(max_length=32)
好处: 至始至终你都没有操作第三张表 全部是orm自动帮你创建的
还内置了四个操作第三种表的方法
add
remove
set
clear
不足: 自动创建的第三张表无法扩展修改字段 表的扩展性差
2.纯手撸(了解)
好处: 第三张表中的字段个数和字段名称全都可以自己定义
不足: 不再支持orm跨表查询 也不支持orm操作表四种方法
class Book(models.Model):
title = models.CharField(max_length=32)
class Authors(models.Model):
name = models.CharField(max_length=32)
class BookToAuthors(models.Model):
book = models.ForeignKey(to='Book')
authors = models.ForeignKey(to='Authors')
create_time = models.DateField(auto_now_add=True)
3.半自动(推荐使用)
好处: 可以任意的添加和修改第三张表中的字段
并且支持orm跨表查询
不足 不支持orm操作表的四种方式
class Book(models.Models):
title = models.CharField(max_length=32)
authors = models.ManyToManyField(to='Authors',through='BookToAuthor',through_fields=('book','authors'))
'''
当你的ManyToManyField只有一个参数to的情况下 orm会自动帮你创建第三张表 如果你加了through和through_fields那么orm就不会自动创建第三张表 但是他会在内部帮你维护关系 让你能够继续使用跨表查询
through 自己指定第三张关系表
through_fields 自己指定第三张关系表中 到底哪两个字段维护着表与表之间的多对多关系
'''
class Authors(models.Model):
name = models.CharField(max_length=32)
books = models.ManyToManyField(to='Book',through='BookToAuthor',through_fields=('authors,book')
class BookToAuthor(models.Model):
book = models.ForeignKey(to='book')
authors = models.ForeignKey(to='Authors')
forms组件
需求:
1.写一个注册页面 获取用户输入的用户名和密码
提交到后端后 需要对用户名和密码做校验
用户名里面不能有毛猫
密码不能少于3位
如果不符合 展示相应的错误信息
1.手动书写html代码获取用户输入 >>> 渲染标签
2.将数据传递给后端做数据校验 >>> 校验数据
3.如果数据有错误 你还展示了错误信息 >>> 展示信息
forms组件能够做的事情就是上面的三步
使用forms组件的前提是 你需要提前写一个类
from django import forms
class MyForm(forms.Form):
username = forms.CharField(max_length=8,min_length=3) # username字段最少3位最多8位
password = forms.CharField(max_length=8,min_length=3) # password字段最少3位最多8位
email = forms.EmailField() # email字段必须时邮箱格式
校验数据
form_obj = views.MyForm({'username':'jason','password':'12','email':'123'}) # 给写好的类 传字典数据(带校验的数据)
form_obj.is_valid() # 查看校验的数据是否合法
Out[5]: False # 只有当你的数据全部符合校验规则的情况下 结果才是True 否则为False
form_obj.is_valid
Out[6]: <bound method BaseForm.is_valid of <MyForm bound=True, valid=False, fields=(username;password;email)>>
form_obj.errors # 查看不符合规则的字符及错误的语句
Out[8]:
{'password': ['Ensure this value has at least 3 characters (it has 2).'],
'email': ['Enter a valid email address.']}
form_obj.cleaned_data # 查看符合校验规则的语句
Out[9]: {'username': 'jason'}
校验规则: forms组件中 定义的字段默认都是必须传值的 不能少传
少写,不满足校验规则都为False, 多写不会影响校验
渲染标签
forms组件只帮你渲染获取用户输入的标签 不会帮你渲染提交按钮 需要你手动添加
<p>forms组件渲染标签方式1:封装程度态高 不推荐使用 但是可以用在本地测试</p>
{{ form_obj.as_p }} <!--自动渲染所有input框 -->
{{ form_obj.as_ul }}
{{ form_obj.as_table }}
<p>forms组件渲染标签方式2:不推荐使用 写起来太烦了</p>
{{ form_obj.username.label }}{{ form_obj.username }}
{{ form_obj.username.label }}{{ form_obj.password }}
{{ form_obj.username.label }}{{ form_obj.email }}
<p>forms组件渲染标签方式3:推荐使用 </p>
{% for form in form_obj %}
<p>{{ form.label }}{{ form }}</p>
{% endfor %}
展示信息
<form action="" method="post" novalidate>
{% for forms in form_obj %}
<p>
{{ forms.label }}{{ forms }}
<span>{{ forms.errors.0 }}</span>
</p>
{% endfor %}
<input type="submit">
</form>
设置报错信息
error_messages={
'max_length':'密码长度最多8位',
'min_length':'密码最短3位',
'required':'密码不能为空',
'invalid':'邮箱格式错误'
}
数据的校验通常前后端都必须有
但是前端的校验可有可无 并且弱不禁风
后端的校验必须要有 并且必须非常的全面
如何告诉浏览器不做校验 form表单中加一个novalidate
参数即可
<form action="" method="post" novalidate>
校验数据
内置的校验器
from django.core.validators import RegexValidator
validators=[
RegexValidator(r'^[0-9]+$', '请输入数字'),
RegexValidator(r'^159[0-9]+$', '数字必须以159开头'),
]
钩子函数 HOOK
当你觉得上面的所有的校验还不能够满足你的需求 你可以考虑使用钩子函数
是一个函数 函数体内你可以写任意的校验代码
在满足前面基本校验的情况下才执行钩子
局部钩子
你想校验单个字段:
def clean_password(self): # 单个钩子用一个少一个
username = self.cleaneed_data.get('username')
if '666' in useranme:
self.add_error('username','无效666') # 给username所对应的框展示错误信息
return username
全局钩子
你想校验多个字段
# 校验密码 确认密码是否一致
def clean(self):
password = self.cleaned_data.get('password')
confirm_password = slef.cleaned_data.get('confirm_password')
if not password == confirm_password:
self.add_error('confirm_password','两次密码不一致')
return self.cleaned_data
其他字段及参数
label input对应的提示信息
initial input框默认值
required 默认为True控制字段是否必填
widget 给input框设置样式及属性
widget=forms.widgets.TextInput({'class':'form-control c1 c2','username':'jason'})
widget=forms.widgets.TextInput(attrs={'class':'form-control c1 c2','username':'jason'})