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

 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表单的更多相关文章

  1. Django学习笔记(6)——Form表单

    知识储备:HTML表单form学习 表单,在前端页面中属于最常见的一个东西了.基本上网站信息的提交都用到了表单,所以下面来学习Django中优雅的表单系统:Form 表单的主要作用是在网页上提供一个图 ...

  2. django系列9--django中的组件(form表单)

    modelform整体 from django import forms from app01 import models import hashlib from django.core.except ...

  3. Django中三种方式写form表单

    除了在html中自己手写form表单外,django还可以通过 继承django.forms.Form 或django.forms.ModelForm两个类来自动生成form表单,下面依次利用三种方式 ...

  4. 72、django之简单验证码实现与form表单钩子函数补充

    本篇主要讲解简单的验证码实现,验证码使用基本都是找现成的组件来实现,用代码实现这个简单功能主要是了解了解验证码内部的实现. 本篇导航: 五位验证码图示 代码实现 登录验证 Form组件钩子函数补充 一 ...

  5. django之简单验证码实现与form表单钩子函数补充

    本篇主要讲解简单的验证码实现,验证码使用基本都是找现成的组件来实现,用代码实现这个简单功能主要是了解了解验证码内部的实现. 本篇导航: 五位验证码图示 代码实现 登录验证 Form组件钩子函数补充 一 ...

  6. Django多对多关系建立及Form组件

    目录 Django多对多关系 1.创建方式一全自动 2.创建方式二纯手撸 3.半自动(推荐使用) forms校验组件 使用forms组件实现注册功能 form常用字段和插件 数据校验 钩子函数 HOO ...

  7. $Django 多对多-自定义第三张表 基于双下划线的跨表查询(补充)

    自定义第三张表的好处:可以定义多个字段, 缺点:查询不方便(有方法解决) 1.第三张表设置外键,联合唯一(查询不方便) class Books(models.Model): name=models.C ...

  8. django 多对多自定义第三张表时的注意事项

    杂交(自定义第三张表+ManyToManyField) # modles.py class Boy(models.Model): name = models.CharField(max_length= ...

  9. Python菜鸟之路:Django 数据验证之钩子和Form表单验证

    一.钩子功能提供的数据验证 对于数据验证,django会执行 full_clean()方法进行验证.full_clean验证会经历几个步骤,首先,对于model的每个字段进行正则验证,正则验证通过后, ...

随机推荐

  1. 允许Root登录Docker ubuntu(MAC主机,使用portainer管理)

    1. 完成ubuntu容器的建立,完成ssh端口映射 2. 进入portainer内容器的console界面完成如下修改 a 刷新安装源:apt-get update b 安装sshd:apt-get ...

  2. URLOS开发基础教程——docker容器的使用方法

    URLOS本是基于docker容器运行,在入门URLOS开发之前,我们首先需要掌握docker的相关基础知识,本篇就以docker容器的基本使用方法为例,快速的让大家对docker有一个全面的印象. ...

  3. VirtualBox下Centos6.8网络配置

    win10环境下,VirtualBox和Centos6.8已经按照完毕,下面配置Centos6.8网络. 1.设置VirtualBox为桥接模式,具体的有三种联网方法,我们参考http://www.c ...

  4. 引用Nuget包Microsoft.EntityFrameworkCore.Tools.DotNet报错

    错误如下 解决方法 使用VS2017或更高版本在改项目右键,选择“编辑xxx.csproj”,并添加如下一句话,就可以成功引用改Nuget包 <PackageReference Include= ...

  5. 小菜鸟之Oracle数据库之事务

    Oracle数据库之事务 1. 什么是事务 在数据库中事务是工作的逻辑单元,一个事务是由一个或多个完成一组的相关行为的SQL语句组成,通过事务机制确保这一组SQL语句所作的操作要么都成功执行,完成整个 ...

  6. CF 1133B Preparation for International Women's Day

    题目链接:http://codeforces.com/problemset/problem/1133/B 题目分析 读完题目,凡是先暴力.....(不用想,第四组数据就TLE了,QAQ) 当两个数的和 ...

  7. n=C(2,n)+k(构造)( Print a 1337-string)Educational Codeforces Round 70 (Rated for Div. 2)

    题目链接:https://codeforc.es/contest/1202/problem/D 题意: 给你一个数 n ( <=1e9 ),让你构造137713713.....(只含有1,3,7 ...

  8. jQuery 实现图片放大两种方式

    jQuery 实现图片放大两种方式 一.利用css样式表实现,多用于后台显示 1.这种比较简单,利用dom元素的hover实现样式切换 <style> img{ cursor: point ...

  9. CF 403D Beautiful Pairs of Numbers

    The sequence of integer pairs (a1, b1), (a2, b2), ..., (ak, bk) is beautiful, if the following state ...

  10. QuickSort(快排)的JAVA实现

    QuickSort的JAVA实现 这是一篇算法课程的复习笔记 用JAVA对快排又实现了一遍. 先实现的是那个easy版的,每次选的排序轴都是数组的最后一个: package com.algorithm ...