目录
多对多三种创建方式
全自动
class Book(models.Model):
title = models.CharField(max_length=32)
authors = models.ManyToManyField(to='Authors')
class Authors(models.Model):
name = model.CharField(max_length=32)
好处:
orm自动创建第三张表
内置了四个操作第三张表的方法
- add
- remove
- set
- clear
坏处:
自动创建的第三张表无法修改字段,表的扩展性差
纯手撸
class Book(models.Model):
title = models.CharField(max_length=32)
class Authors(models.Model):
name = models.CharField(max_length=32)
class Book2Authors(models.Model):
book = models.ForeignKey(to="Book")
author = models.ForeignKey(to="Authors")
create_time = models.DateField(auto_now_add = True)
好处:
第三张表中字段个数和字段名称可以进行自定义
坏处:
不再支持orm跨表查询,也不再有正反向的概念,也没有add等方法
半自动
推荐使用的创建方式
class Book(models.Model):
title = models.CharField(max_length=32)
authors = models.ManyToMany(to='Authors',through='Book2Author',throuth_fields=("book","authors"))
# 当ManyToManyField只有一个参数to的情况下,orm会自动创建第三张表
# 如果加了through和through_fields,orm就不会自动创建,但是会在内部维护关系,让我们能够继续使用orm跨表查询
# through:自定指定第三张关系表
# through_fields: 自己指定第三张关系表中,到底哪两个字段维护着表与表之间的多对多关系
class Authors(models.Model):
name = models.CharField(max_length=32)
books = models.ManyToManyField(to='Book', through='Book2Author', through_fields=("authors","book"))
class Book2Author(models.Model):
book = models.ForeignKey(to='Book')
authors = models.ForeignKey(to='Authors')
# 该表中可以由任意多的外键字段
# 可以扩展任意的字段
好处:
可以任意的添加和修改第三张表中的字段,并且支持ORM跨表查询
坏处:
不支持add等方法
forms 校验性组件
form组件的常用字段
initial:初始值,input框里面的初始值
error_messages:重写错误信息
password:密文
radioselect:单radio值为字符串
label:input对应的提示信息
required:默认为True控制字段是否必填
widget:给input框设置样式及属性
form组件的主要功能:
- 生成页面可用的HTML标签
- 对用户提交的数据金进行校验
- 保留上次输入的内容
使用forms组件的前提需要导入forms模块
再写一个类:
class MyForm(forms.Form):
username=forms.CharField(max_length=8,min_length=3)
password = forms.Charfield(max_length=8,min_length=3)
email = forms.EmailField()
校验数据
# 给写好的类传字典数据
form_obj = views.MyForm({'username':'qqq','password':'123','email':'123@qq.com'})
# 查看校验的数据是否合法
form_obj.is_valid() # 只有当数据全部符合校验规则,结果才是True
# 查看不符合规则的字段以及错误的理由
form_obj.errors
# 查看符合校验规则的数据
form_obj.cleaned_data
注意:forms组件中,定义的字段默认都是必须传值的,不能少传,但是多传不会有任何影响
渲染标签
forms组件只会渲染获取用户输入的标签,不会渲染提交按钮
-
forms组件渲染标签方式1:
{{form_obj.as_p}} <!--自动渲染所有input框--> {{form_obj.as_ul}} {{form_obj.as_table}}
封装程度太高,不推荐使用
-
forms组件渲染标签方式2:
{{ form_obj.username.label}}{{form_obj.username}} {{ form_obj.password.label}}{{form_obj.password}} {{ form_obj.email.label}}{{form_obj.email}}
写起来麻烦,不推荐使用
-
forms组件渲染标签方法3
{% for form in form_obj %} <p>{{ form.label }}{{ form}}</p> <!--form 等价于方式2中的对象.字段名--> {% endfor %}
展示信息
<p>forms组件渲染标签方式3:推荐使用 </p>
<form action="" method="post" novalidate>
{% for forms in form_obj %}
<p>
{{ forms.label }}{{ forms }}
<span>{{ forms.errors.0 }}</span>
</p> <!--form 等价于你方式2中的对象点字段名-->
{% endfor %}
<input type="submit">
</form>
内置的校验器
from django.core.validators import RegexValidator
validators=[
RegexValidator(r'^[0-9]+$', '请输入数字'),
RegexValidator(r'^159[0-9]+$', '数字必须以159开头'), ]
钩子函数
局部钩子
在form类中定义clean_字段名()
方法,实现对特定字段进行校验
def clean_username(self):
username = self.cleaned_data.get('username')
if '666' in username:
# 给username所对应的框展示错误信息
# self.add_error('username','光喊666是不行的')
raise ValidationError('到底对不对啊')
# 将username数据返回
return username
全局钩子
在form类中定义clean()
方法,就能实现对字段进行全局校验
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