day 57小结

多对多三种创建方式

​ 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'})

原文地址:https://www.cnblogs.com/LZF-190903/p/11987072.html