一、多对多建表的三种创建方式:

 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所有内置字段

最新文章

  1. average slice
  2. 基于bootstrap 的datatable插件的使用2(php版)
  3. C#快捷键
  4. 【译】Learn ES2015——箭头函数
  5. ubuntu使用root用户登录/切换root权限
  6. 最新IP地址数据库
  7. php中位运算的应用:货品的状态
  8. docker入门(二)
  9. Android应用截图嵌入到真实设备
  10. grunt getHTML
  11. java内存模型6-final
  12. 团队作业5——测试与发布(Alpha版本)
  13. Linux必知必会的目录与启动过程
  14. js 基础知识总结
  15. BZOJ2326 HNOI2011数学作业(矩阵快速幂)
  16. C#.NET常见问题(FAQ)-如何使用变量访问控件属性
  17. 【learning】vim爆改记 (如何让vim用起来像devc++)
  18. TCP/IP详解(整理)
  19. windows下gvim中文乱码解决方案
  20. [转] Ansible 进阶 | facts 缓存

热门文章

  1. 转-Uptime与数据中心等级认证
  2. react中key的使用
  3. 机器学习实战笔记——KNN约会网站
  4. Git_mergetool_tutorial(转载)
  5. 【Linux开发】linux设备驱动归纳总结(四):1.进程管理的相关概念
  6. solr设置分片和副本
  7. [转] DLL加载方式
  8. Minimum Score Triangulation of Polygon
  9. [转帖]PostgreSQL与MySQL比较 From 2010年
  10. spring笔记3路径跳转