多对多的三种创建方式
1、全自动(推荐使用的**)
优势:第三张可以任意的扩展字段
缺点:ORM查询不方便,如果后续字段增加更改时不便添加修改
manyToManyField创建的第三张表属于虚拟的,后缀会自动添加有_id的外键字段
创建的方式:
2、纯手动(不推荐使用)
需要手动创第三方表
优势:第三张表可以任意的扩展字段
缺点:ORM查询不便
3、半自动(推荐使用***)
优势:结合了全自动和半自动的两个优点,把建表的关系直接在一张表上表示出来
这样创建的表,在多对多时不支持ORM的操作有以下几种:
""" 多对多字段的 add set remove clear不支持 """
Form组件
forms组件功能
1、校验功能:
- 就是将form表单中的值在post请求发送到服务端时,服务端利用forms组件去检验是否符合规则
- form表单中的name属性值要和自定义forms组件的字段一致。
2、标签的渲染功能
3、渲染错误的信息
4、局部钩子,再次检验
使用forms组件是实现注册功能
简单的注册功能的版本:
实现简单的校验功能。设置条件,在注册的时候进行有效的检验
views.py
from django.shortcuts import render,reverse,redirect,HttpResponse from django.core.exceptions import ValidationError # Create your views here. def login(request): errors = {'username':'','password':''} if request.method=='POST': username = request.POST.get('username') password = request.POST.get('password') if '黄赌毒' in username: errors['username'] = '属于违法,警惕' if len(password)<6: errors['password'] = '密码过短,不安全' return render(request,'login.html',locals())
login.html:
在提交的按钮,输入框中绑定提示的错误信息,校验的条件在后端进行
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script> </head> <body> <form action="" method="post"> <p>username: <input type="text" name="username"> <span style="color: red">{{ errors.username }}</span> </p> <p>password: <input type="password" name="password"> <span style="color: red">{{ errors.password }}</span> </p> <input type="submit"> </form> </body> </html>
总结:forms组件能够直接完成以下的三部分
1.渲染前端页面
2.校验数据是否合法
3.展示错误信息
forms组件的基本用法
基本的校验规则:
先写好一个继承了forms.Form的类
from django import forms class LoginForm(forms.Form): username = forms.CharField(max_length=8,min_length=3) # 用户名最长八位最短三位 password = forms.CharField(max_length=8,min_length=5) # 密码最长八位最短五位 email = forms.EmailField() # email必须是邮箱格式
forms的校验规则:根据字段一个个进行比对,符合条件和错误的分别的保存起来
forms基本的使用
1.将需要校验的数据,以字典的方式传递给自定义的类,实例化产生对象 form_obj = views.LoginForm({'username':'jason','password':'123','email':'123'})2.如何查看数据是否全部合法 form_obj.is_valid() # 只有所有的数据都符合要求 才会是True False3.如何查看错误原因 form_obj.errors { 'password': ['Ensure this value has at least 5 characters (it has 3).'], 'email': ['Enter a valid email address.'] }4.如何查看通过校验的数据 form_obj.cleaned_data {'username': 'jason'}直接在pycharm终端输入命令进行校验:
注意事项:
1.自定义类中所有的字段默认都是必须要传值的
2.可以额外传入类中没有定义的字段名 forms组件不会去校验 也就意味着多传一点关系没有
在书写的字段内;只能多传不能少传。
forms三种渲染方式
书写from表单的三种方法:
前端简单的from表单如下,原始的
在Django中利用forms组件书写的from表单又以下三种方法:
先在后端开启路由向前端传递数据信息,views.py
def register(request): # 先生成一个空白的自定义类对象 form_obj = LoginForm() # 将该对象传递给前端 return render(requesr,'register.html')
前端书写的register.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script> </head> <body> <form action="" method='post' novalidate> <p>第一种渲染页面的方式(封装程度太高 一般只用于本地测试 通常不适用)</p> {{ form_obj.as_p }} {{ form_obj.as_ul }} {{ form_obj.as_table }} <p>第二种渲染页面的方式(可扩展性较高 书写麻烦)</p> <p>{{ form_obj.username.label }}{{ form_obj.username }}</p> <p>{{ form_obj.password.label }}{{ form_obj.password }}</p> <p>{{ form_obj.email.label }}{{ form_obj.email }}</p> <p>第三种渲染页面的方式(推荐)</p> {% for foo in form_obj %} <p>{{ foo.label }}:{{ foo }} <span>{{ foo.errors.0 }}</span> </p> {% endfor %} <input type="submit"> </form> </body> </html>
1、第一种渲染页面的方式(封装程度太高 一般只用于本地测试 通常不适
2、
第二种渲染页面的方式(可扩展性较高 书写麻烦)
3、
第三种渲染页面的方式(推荐)
forms组件展示错误的信息提示
moldes.py,建表的时候指定校验的方式,和条件
from django import forms from django.core.validators import RegexValidator from django.forms import widgets class LoginForm(forms.Form): username = forms.CharField(max_length=8,min_length=3,label='用户名',initial='tankdsb', error_messages={ 'max_length':'用户名最大八位', 'min_length':'用户名最小三位', 'required':'用户名不能为空' },widget=widgets.TextInput() ) # 用户名最长八位最短三位 password = forms.CharField(max_length=8,min_length=5,label='密码',error_messages={ 'max_length':'密码最大八位', 'min_length':'密码最小五位', 'required':'密码不能为空' }, widget=widgets.PasswordInput(attrs={'class':'form-control c1 c2','username':'jason'}) ) # 密码最长八位最短五位 confirm_password = forms.CharField(max_length=8, min_length=5, label='确认密码', error_messages={ 'max_length': '确认密码最大八位', 'min_length': '确认密码最小五位', 'required': '确认密码不能为空' }, required=False, validators=[RegexValidator(r'^[0-9]+$', '请输入数字'), RegexValidator(r'^159[0-9]+$', '数字必须以159开头')]) # 密码最长八位最短五位 email = forms.EmailField(label='邮箱',error_messages={ 'required':'邮箱不能为空', 'invalid':'邮箱格式不正确' }) # email必须是邮箱格式
views.py
def reg(request): # 1 现生成一个空的自定义类的对象 form_obj = LoginForm() # 2 将该对象传递给前端页面 if request.method == 'POST': # 3 获取前端post请求提交过来的数据 # print(request.POST) # 由于request.POST其实也是一个字典,所有可以直接传给LoginForm form_obj = LoginForm(request.POST) # 4 校验数据 让forms组件帮你去校验 if form_obj.is_valid(): # 5 如果数据全部通过 应该写入数据库 pass # 6 如果不通过 一个像前端展示错误信息 return render(request,'reg.html',locals())
前端html
注意事项:
1.forms组件在帮你渲染页面的时候,只会渲染获取用户输入的标签 ,提交按钮需要你手动添加
2.input框的label注释 ,不指定的情况下,默认用的类中字段的首字母大写
关键字:novalidate
告诉前端取消掉自带的校验方式,form标签指定novalidate属性即可,让后端来书写
前端自带的校验方法:
字段的校验
掌握的自定义字段,用正则表达式书写校验规则,手机号的验证:
RegexValidator验证器
from django.forms import Form from django.forms import widgets from django.forms import fields from django.core.validators import RegexValidator class MyForm(Form): user = fields.CharField( validators=[RegexValidator(r'^[0-9]+$', '请输入数字'), RegexValidator(r'^159[0-9]+$', '数字必须以159开头')], )
自定义验证函数(了解)
自定义的验证函数方法
钩子函数(HOOK)
就是forms组件暴漏给用户的,可以自定义额外的检验规则;必须写在Form类里面
局部钩子
我们在Fom类中定义 clean_字段名() 方法,就能够实现对特定字段进行校验。
局部钩子(针对某一个字段做额外的校验) 校验用户名中不能包含666 一旦包含 提示
def clean_username(self): username = self.cleand_data.get('username') if '666' in username: self.add_error('username','密码有危险提示,请从新修改哦') return username
全局钩子函数
全局钩子(针对多个字段做额外的校验) 校验用户两次密码是否一致
有password和confirm_password两个字段:
# 全局钩子(针对多个字段做额外的校验) 校验用户两次密码是否一致 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
forms组件其他字段及其他操作的使用
""" required 是否必填 label 注释信息 error_messages 报错信息 initial 默认值 widget 控制标签属性和样式 widget = widgets.PasswordInput() 控制标签属性 widget = widgets.PasswordInput(attrs={'class': 'form-control c1 c2', 'username': 'jason'}) """多个类就空格格开书写:c2 c2
其他字段了解知识点(知道有这些对象 需要用到的时候 能够知道去哪找)
# 单选的radio框 gender = forms.ChoiceField( choices=((1, "男"), (2, "女"), (3, "保密")), label="性别", initial=3, widget=forms.widgets.RadioSelect() ) # 单选select hobby = forms.ChoiceField( choices=((1, "篮球"), (2, "足球"), (3, "双色球"),), label="爱好", initial=3, widget=forms.widgets.Select() ) # 多选的select框 hobby1 = forms.MultipleChoiceField( choices=((1, "篮球"), (2, "足球"), (3, "双色球"),), label="爱好", initial=[1, 3], widget=forms.widgets.SelectMultiple() ) # 单选的checkbox keep = forms.ChoiceField( label="是否记住密码", initial="checked", widget=forms.widgets.CheckboxInput() ) # 多选的checkbox hobby2 = forms.MultipleChoiceField( choices=((1, "篮球"), (2, "足球"), (3, "双色球"),), label="爱好", initial=[1, 3], widget=forms.widgets.CheckboxSelectMultiple() ) phone = forms.CharField( validators=[RegexValidator(r'^[0-9]+$', '请输入数字'), RegexValidator(r'^159[0-9]+$', '数字必须以159开头')], )
具体的展示:
forms组件的源码分析
通过源码解析,看Django内部的forms组件是如何是实现校验的原理的;大致了解