Django-多对多建表与Form表单
一、多对多建表的三种创建方式:
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.纯手撸型:(了解即可)
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,remove,set,clear方法。
3.半自动型:(推荐使用)
class Book(models.Model):
title = models.CharField(max_length=32)
# 多对多关系字段
authors = models.ManyToManyField(to='Authors',through='Book2Author',through_fields=("book","authors"))
"""
当你的ManyToManyField只有一个参数to的情况下 orm会自动帮你创建第三张表;
如果你加了through和through_fields那么orm就不会自动帮你创建第三张表 ;
但是它会在内部帮你维护关系,让你能够继续使用orm的跨表查询
through 指自定义的第三张关系表
through_fields 自动指定第三张关系表中,到底哪两个字段维护者表与表之间的多对多关系
""" class Authors(models.Model):
name = models.CharField(max_length=32)
# 多对多关系字段 等价于上面的book表中的多对多关系字段
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,remove,set,clear方法
二、Forms组件:
1.Forms组件介绍:
Form组件可以做的几件事情:
1.用户请求数据的验证;
2.自动生成错误信息;
3.打包用户提交的正确信息;
4.如果其中有一个错误了,其他的正确,保留上次输入的内容
5.自动创建input标签并可以设置样式
2.Form组件的使用:
(1).创建规则:
class Foo(Form): #必须继承
username = xxx
password = xxx
email = xxx
注意这里的字段必须和input的name字段一致
(2).数据和规则进行匹配先导入view.py
from django.forms import Form
from django.forms import fields
from django.forms import widgets
使用forms组件的第一步,必须先写一个类:
from django import forms
from django.core.validators import RegexValidator
from django.forms import widgets
from django.core.exceptions import ValidationError
class MyForm(forms.Form):
# username字段 最少三位 最多八位,label设置input前面的字段,inital设置默认值
username = forms.CharField(max_length=8,min_length=3,label='用户名',initial='默认值',
#通过error_messages,设置中文提示的错误信息
error_messages={
'max_length':'用户名最长八位',
'min_length':'用户名最短三位',
'required':'用户名不能为空'
},required=False,# False可以不进行Form验证,默认为True
#通过widget=forms.widgets可以对标签属性设置,
widget=forms.widgets.TextInput({'class':'form-control c1 c2','username':'jason'})
)
# password字段 最少三位 最多八位
password = forms.CharField(max_length=8,min_length=3,label='密码',
error_messages={
'max_length': '密码最长八位',
'min_length': '密码最短三位',
'required': '密码不能为空'
},widget=forms.widgets.PasswordInput()
)
confirm_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':'邮箱格式错误'
}) 当你觉得上面的所有的校验还不能满足你的需求,你可以考虑使用钩子函数,函数体内你可以写任意的校验代码
利用钩子函数进行限定用户输入:
# 校验用户名中不能含有666 局部钩子
def clean_username(self):
username = self.cleaned_data.get('username')
if '' in username:
# 给username所对应的框展示错误信息
# self.add_error('username','光喊666是不行的')
raise ValidationError('到底对不对啊')
# 将username数据返回
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 函数调用:
def index(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组件入口就是is_valid()
print(form_obj.cleaned_data)
return HttpResponse('数据全部OK')
# 直接将生成的对象 传递给前端页面
return render(request,'index.html',locals()) 数据的校验通常前后端都必须有的,但是前端的校验可有可无,并且弱不禁风,后端的校验必须有并且必须非常全面,
如何告诉浏览器不做校验,form表单中加一个novalidate参数即可。
#<form action="" method="post" novalidate>
index.html文件:
form action="" method="post" novalidate>
{% for forms in form_obj %}
<p>
{{ forms.label }}{{ forms }}
<span>{{ forms.errors.0 }}</span>
</p> <!--<span>{{ forms.errors.0 }}获取错误信息添加input的后面-->
{% endfor %}
<input type="submit">
</form>
2.Form组件的其他方法使用:
radioSelect,单radio值为字符串
gender = forms.fields.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 hobby = 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 hobby = forms.MultipleChoiceField(
choices=((1, "篮球"), (2, "足球"), (3, "双色球"),),
label="爱好",
initial=[1, 3],
widget=forms.widgets.CheckboxSelectMultiple()
)
Form所有内置字段
Field
required=True, 是否允许为空
widget=None, HTML插件
label=None, 用于生成Label标签或显示内容
initial=None, 初始值
help_text='', 帮助信息(在标签旁边显示)
error_messages=None, 错误信息 {'required': '不能为空', 'invalid': '格式错误'}
validators=[], 自定义验证规则
localize=False, 是否支持本地化
disabled=False, 是否可以编辑
label_suffix=None Label内容后缀 CharField(Field)
max_length=None, 最大长度
min_length=None, 最小长度
strip=True 是否移除用户输入空白 IntegerField(Field)
max_value=None, 最大值
min_value=None, 最小值 FloatField(IntegerField)
... DecimalField(IntegerField)
max_value=None, 最大值
min_value=None, 最小值
max_digits=None, 总长度
decimal_places=None, 小数位长度 BaseTemporalField(Field)
input_formats=None 时间格式化 DateField(BaseTemporalField) 格式:2015-09-01
TimeField(BaseTemporalField) 格式:11:12
DateTimeField(BaseTemporalField)格式:2015-09-01 11:12 DurationField(Field) 时间间隔:%d %H:%M:%S.%f
... RegexField(CharField)
regex, 自定制正则表达式
max_length=None, 最大长度
min_length=None, 最小长度
error_message=None, 忽略,错误信息使用 error_messages={'invalid': '...'} EmailField(CharField)
... FileField(Field)
allow_empty_file=False 是否允许空文件 ImageField(FileField)
...
注:需要PIL模块,pip3 install Pillow
以上两个字典使用时,需要注意两点:
- form表单中 enctype="multipart/form-data"
- view函数中 obj = MyForm(request.POST, request.FILES) URLField(Field)
... BooleanField(Field)
... NullBooleanField(BooleanField)
... ChoiceField(Field)
...
choices=(), 选项,如:choices = ((0,'上海'),(1,'北京'),)
required=True, 是否必填
widget=None, 插件,默认select插件
label=None, Label内容
initial=None, 初始值
help_text='', 帮助提示 ModelChoiceField(ChoiceField)
... django.forms.models.ModelChoiceField
queryset, # 查询数据库中的数据
empty_label="---------", # 默认空显示内容
to_field_name=None, # HTML中value的值对应的字段
limit_choices_to=None # ModelForm中对queryset二次筛选 ModelMultipleChoiceField(ModelChoiceField)
... django.forms.models.ModelMultipleChoiceField TypedChoiceField(ChoiceField)
coerce = lambda val: val 对选中的值进行一次转换
empty_value= '' 空值的默认值 MultipleChoiceField(ChoiceField)
... TypedMultipleChoiceField(MultipleChoiceField)
coerce = lambda val: val 对选中的每一个值进行一次转换
empty_value= '' 空值的默认值 ComboField(Field)
fields=() 使用多个验证,如下:即验证最大长度20,又验证邮箱格式
fields.ComboField(fields=[fields.CharField(max_length=20), fields.EmailField(),]) MultiValueField(Field)
PS: 抽象类,子类中可以实现聚合多个字典去匹配一个值,要配合MultiWidget使用 SplitDateTimeField(MultiValueField)
input_date_formats=None, 格式列表:['%Y--%m--%d', '%m%d/%Y', '%m/%d/%y']
input_time_formats=None 格式列表:['%H:%M:%S', '%H:%M:%S.%f', '%H:%M'] FilePathField(ChoiceField) 文件选项,目录下文件显示在页面中
path, 文件夹路径
match=None, 正则匹配
recursive=False, 递归下面的文件夹
allow_files=True, 允许文件
allow_folders=False, 允许文件夹
required=True,
widget=None,
label=None,
initial=None,
help_text='' GenericIPAddressField
protocol='both', both,ipv4,ipv6支持的IP格式
unpack_ipv4=False 解析ipv4地址,如果是::ffff:192.0.2.1时候,可解析为192.0.2.1, PS:protocol必须为both才能启用 SlugField(CharField) 数字,字母,下划线,减号(连字符)
... UUIDField(CharField) uuid类型
Form所有内置字段
Django-多对多建表与Form表单的更多相关文章
- Django学习笔记(6)——Form表单
知识储备:HTML表单form学习 表单,在前端页面中属于最常见的一个东西了.基本上网站信息的提交都用到了表单,所以下面来学习Django中优雅的表单系统:Form 表单的主要作用是在网页上提供一个图 ...
- django系列9--django中的组件(form表单)
modelform整体 from django import forms from app01 import models import hashlib from django.core.except ...
- Django中三种方式写form表单
除了在html中自己手写form表单外,django还可以通过 继承django.forms.Form 或django.forms.ModelForm两个类来自动生成form表单,下面依次利用三种方式 ...
- 72、django之简单验证码实现与form表单钩子函数补充
本篇主要讲解简单的验证码实现,验证码使用基本都是找现成的组件来实现,用代码实现这个简单功能主要是了解了解验证码内部的实现. 本篇导航: 五位验证码图示 代码实现 登录验证 Form组件钩子函数补充 一 ...
- django之简单验证码实现与form表单钩子函数补充
本篇主要讲解简单的验证码实现,验证码使用基本都是找现成的组件来实现,用代码实现这个简单功能主要是了解了解验证码内部的实现. 本篇导航: 五位验证码图示 代码实现 登录验证 Form组件钩子函数补充 一 ...
- Django多对多关系建立及Form组件
目录 Django多对多关系 1.创建方式一全自动 2.创建方式二纯手撸 3.半自动(推荐使用) forms校验组件 使用forms组件实现注册功能 form常用字段和插件 数据校验 钩子函数 HOO ...
- $Django 多对多-自定义第三张表 基于双下划线的跨表查询(补充)
自定义第三张表的好处:可以定义多个字段, 缺点:查询不方便(有方法解决) 1.第三张表设置外键,联合唯一(查询不方便) class Books(models.Model): name=models.C ...
- django 多对多自定义第三张表时的注意事项
杂交(自定义第三张表+ManyToManyField) # modles.py class Boy(models.Model): name = models.CharField(max_length= ...
- Python菜鸟之路:Django 数据验证之钩子和Form表单验证
一.钩子功能提供的数据验证 对于数据验证,django会执行 full_clean()方法进行验证.full_clean验证会经历几个步骤,首先,对于model的每个字段进行正则验证,正则验证通过后, ...
随机推荐
- 统计学习方法 | 第3章 k邻近法
第3章 k近邻法 1.近邻法是基本且简单的分类与回归方法.近邻法的基本做法是:对给定的训练实例点和输入实例点,首先确定输入实例点的个最近邻训练实例点,然后利用这个训练实例点的类的多数来预测输入实例 ...
- mysql——修改表名、修改字段名、修改字段数据类型、增加字段、删除字段、修改字段排列位置、修改存储引擎、删除表 (示例)
一.创建表和插入数据: ), mz ), bz ) ); ,'sww','sww01'); ,'aww','aww02'); ,'qww','qww03'), (,'eww','eww04'), (, ...
- python 爬虫 urllib模块 发起post请求
urllib模块发起的POST请求 案例:爬取百度翻译的翻译结果 1.通过浏览器捉包工具,找到POST请求的url 针对ajax页面请求的所对应url获取,需要用到浏览器的捉包工具.查看百度翻译针对某 ...
- hashmap C++实现
hashmap.h #ifndef _HASHMAP_H_ #define _HASHMAP_H_ template<class Key, class Value> class HashN ...
- ideal中运行manven常用操作
ideal中对项目打包,输入命令如下图所示: clean install -Dmaven.test.skip=true
- 2-SAT问题介绍求解 + 模板题P4782
(点击此处查看原题) 什么是2-SAT问题 sat 即 Satisfiability,意思为可满足,那么2-SAT表示一些布尔变量只能取true或者false,而某两个变量之间的值存在一定的关系(如: ...
- KMP(next数组的更新理解)Codeforces Round #578 (Div. 2)--Compress Words
题目链接:https://codeforc.es/contest/1200/problem/E 题意: 有n串字符串,让你连起来:sample please ease in out ---> ...
- python线程中的同步问题
多线程开发可能遇到的问题 假设两个线程t1和t2都要对num=0进行增1运算,t1和t2都各对num修改1000000次,num的最终的结果应该为2000000.但是由于是多线程访问,有可能出现下面情 ...
- 使用Python的文本挖掘的特征选择/提取
在文本挖掘与文本分类的有关问题中,文本最初始的数据是将文档表示成向量空间模型的一个矩阵,而这个矩阵所拥有的就是不同的词,常采用特征选择方法.原因是文本的特征一般都是单词(term),具有语义信息,使用 ...
- 1,全局变量;2,图形验证码;3,解决bug的毅力
通过这一整天的学习,主要解决了这三个: 1,全局变量 在函数外部定义: var gloabl: function test(){ global = " ": //不能写成va ...