一、多对多三种创建方式

(一)全自动

  1. ORM自动创建第三张表,不用对第三张表进行操作,内置了四个方法(add、remove、set、clear)
  2. 可扩展性差,第三张表无法扩展或修改字段
from django.db import models
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)

(二)纯手撸(基本不用)

  1. 第三张表的字段个数和字段名称全部可以自己定义
  2. 不再支持ORM跨表查询和四个内置方法(add、set、remove、clear)
from django.db import models
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)

(三)半自动(推荐使用)

  1. through:自定义指定第三张关系表
  2. through_fields:元组形式自定义指定第三张表中的关联字段(顺序和表有关,哪个表创建的,哪个字段放前面)
  3. 可以任意添加和修改地第三张表中字段
  4. 支持ORM跨表查询,不支持四种内置方法(add、set、remove、clear)
from django.db import models
class Book(models.Model):
    title = models.CharField(max_length=32)

    # 多对多关系字段
    authors = models.ManyToManyField(to='Authors',through='Book2Authors',through_fields=('book','authors'))

class Authors(models.Model):
    name = models.CharField(max_length=32)
    # books = models.ManyToManyField(to='Book',through='Book2Authors',through_fields=('authors','book'))

class Book2Authors(models.Model):
    book = models.ForeignKey(to='Book')
    authors = models.ForeignKey(to='Authors')

二、forms组件

需要导入froms:from django import forms

(一)校验数据

(1)常用内置字段及参数

所有字段默认继承Field,即Field中的参数都可以使用

  • Field

    1. required=True:是否允许为空
    2. label:label标签内显示的内容,默认首字母大写的字段名
    3. initial:初始值
    4. error_messages:设置错误信息,格式{‘参数名’:‘错误信息’},比如{‘required’:‘为空时显示的错误信息内容’}
    5. widget:html插件
    6. validators:自定义验证规则,里面放元组,与RegexValidator联用
  • CharField
    1. max_length:最大长度
    2. min_length:最小长度
    3. strip:是否移除空白
    4. widget:设置标签type参数以及添加属性,默认为text,`* TextInput(字典):设置标签type参数为text,同时可以添加自定义属性或样式,如:widget=forms.widgets.TextInput({'class':'form-control c1 c2','username':'jason'})* PasswordInput():设置标签type参数为password,如:widget=forms.widgets.PasswordInput()`
  • ChoiceField/MultipleChoiceField
    1. choices :choices参数,如:choices = ((0,'上海'),(1,'北京'),)
    2. required:是否必填
    3. widget:插件,默认为select
      • RadioSelect():标签type参数为radio
      • Select():select下拉框标签
      • CheckboxInput():是否记住密码
      • SelectMultiple():select下拉框标签多选
      • CheckboxSelectMultiple:标签type参数为checkbox
  • EmailField

    必须是邮箱格式

from django import forms

class MyForm(forms.Form):
    # username字段 最少三位 最多八位
    username = forms.CharField(max_length=8,min_length=3)
    # password字段 最少三位  最多八位
    password = forms.CharField(max_length=8,min_length=3)
    # email字段 必须是邮箱格式
    email = forms.EmailField()

(2)内置的校验器

  1. 通过validators参数指向设置校验器,列表形式,可以放多个
  2. RegexValidator(正则表达式,条件未满足时输出的字符串)
from django.core.validators import RegexValidator

class MyForm(Form):
    user = fields.CharField(
        validators=[RegexValidator(r'^[0-9]+$', '请输入数字'), RegexValidator(r'^159[0-9]+$', '数字必须以159开头')],
    )

(3)HOOK方法

  • 局部钩子函数

    1. 校验单个字段
    2. 在Form类中定义clean_字段名()方法
    3. cleaned_data:前面两种筛选均满足的数据,字典形式存储
    4. 通过ValidationError(错误信息)直接抛出错误,源码内部做了异常捕捉
    5. 通过add_error(字段名,错误信息)方法添加错误
    from django.core.exceptions import ValidationError
    class LoginForm(forms.Form):
        username = forms.CharField(
            min_length=8,
            label="用户名",
            initial="张三",
            error_messages={
                "required": "不能为空",
                "invalid": "格式错误",
                "min_length": "用户名最短8位"
            },
            widget=forms.widgets.TextInput(attrs={"class": "form-control"})
        )
        ...
        # 定义局部钩子,用来校验username字段
            def clean_username(self):
            username = self.cleaned_data.get('username')
            if '666' in username:
                # 给username所对应的框展示错误信息
                # self.add_error('username','光喊666是不行的')
                raise ValidationError('到底对不对啊')
            # 将username数据返回
            return username
  • 全局钩子函数

    1. 对多个字段进行校验
    2. 在Form类中定义clean()方法
  class LoginForm(forms.Form):
      ...
      password = forms.CharField(
          min_length=6,
          label="密码",
          widget=forms.widgets.PasswordInput(attrs={'class': 'form-control'}, render_value=True)
      )
      re_password = forms.CharField(
          min_length=6,
          label="确认密码",
          widget=forms.widgets.PasswordInput(attrs={'class': 'form-control'}, render_value=True)
      )
      ...
      # 定义全局的钩子,用来校验密码和确认密码字段是否相同
      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

(二)渲染标签

(1)后端

  1. POST请求前后form对象名要相同,方便后续错误信息展示和保存信息状态
  2. is_valid:是否满足匹校验条件,返回布尔值
# views.py
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())

(2)前端

form组件只会渲染获取用户输入的标签,不会渲染提交按钮想

  • 方式1(内置方法)

    方式1封装程度太高,扩展性差,不推荐使用

    1. as_p:作为p标签
    2. as_ul:作为列表标签
    3. as_table:作为表格表头标签,效果为横向一排
    {{ form_obj.as_p }}  <!--自动渲染所有input框  -->
    {{ form_obj.as_ul }}
    {{ form_obj.as_table }}
  • 方式2(label属性)

    方式2在输入项目过多时过于冗杂,也不推荐使用

    {{ form_obj.username.label }}{{ form_obj.username }}
    {{ form_obj.username.label }}{{ form_obj.password }}
    {{ form_obj.username.label }}{{ form_obj.email }}
    
  • 方式3(for循环)

    推荐使

    {% for form in form_obj %}
        <p>{{ form.label }}{{ form }}</p>  <!--form 等价于你方式2中的对象点字段名-->
    {% endfor %}

(三)展示信息

  1. 空的Form对象和POST请求后的Form对象名要相同
  2. errors:错误信息,返回列表
  3. form表单中novalidate参数:取消前端校验
<form action="" method="post" novalidate>
    {% for forms in form_obj %}
    <p>
        {{ forms.label }}{{ forms }}
        <span>{{ forms.errors.0 }}</span>
    </p>  <!--form 等价于你方式2中的对象点字段名-->
    {% endfor %}
    <input type="submit">
</form>

三、Form组件模板

(一)initial

初始值,input框里面的初始值。

class LoginForm(forms.Form):
    username = forms.CharField(
        min_length=8,
        label="用户名",
        initial="张三"  # 设置默认值
    )
    pwd = forms.CharField(min_length=6, label="密码")

(二)error_messages

重写错误信息。

class LoginForm(forms.Form):
    username = forms.CharField(
        min_length=8,
        label="用户名",
        initial="张三",
        error_messages={
            "required": "不能为空",
            "invalid": "格式错误",
            "min_length": "用户名最短8位"
        }
    )
    pwd = forms.CharField(min_length=6, label="密码")

(三)password

class LoginForm(forms.Form):
    ...
    pwd = forms.CharField(
        min_length=6,
        label="密码",
        widget=forms.widgets.PasswordInput(attrs={'class': 'c1'}, render_value=True)
    )

(四)radioSelect

单radio值为字符串

class LoginForm(forms.Form):
    username = forms.CharField(
        min_length=8,
        label="用户名",
        initial="张三",
        error_messages={
            "required": "不能为空",
            "invalid": "格式错误",
            "min_length": "用户名最短8位"
        }
    )
    pwd = forms.CharField(min_length=6, label="密码")
    gender = forms.fields.ChoiceField(
        choices=((1, "男"), (2, "女"), (3, "保密")),
        label="性别",
        initial=3,
        widget=forms.widgets.RadioSelect()
    )

(五)单选Select

class LoginForm(forms.Form):
    ...
    hobby = forms.ChoiceField(
        choices=((1, "篮球"), (2, "足球"), (3, "双色球"), ),
        label="爱好",
        initial=3,
        widget=forms.widgets.Select()
    )

(六)多选Select

class LoginForm(forms.Form):
    ...
    hobby = forms.MultipleChoiceField(
        choices=((1, "篮球"), (2, "足球"), (3, "双色球"), ),
        label="爱好",
        initial=[1, 3],
        widget=forms.widgets.SelectMultiple()
    )

(七)单选checkbox

class LoginForm(forms.Form):
    ...
    keep = forms.ChoiceField(
        label="是否记住密码",
        initial="checked",
        widget=forms.widgets.CheckboxInput()
    )

(八)多选checkbox

class LoginForm(forms.Form):
    ...
    hobby = forms.MultipleChoiceField(
        choices=((1, "篮球"), (2, "足球"), (3, "双色球"),),
        label="爱好",
        initial=[1, 3],
        widget=forms.widgets.CheckboxSelectMultiple()

四、附录

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类型

Django Form内置字段

(day57)九、多对多创建的三种方式、Forms组件的更多相关文章

  1. 于Unity3D动态创建对象和创建Prefab三种方式的原型对象

    于Unity3D动态创建对象和创建Prefab三种方式的原型对象 u3d在动态创建的对象,需要使用prefab 和创建时 MonoBehaviour.Instantiate( GameObject o ...

  2. 黑马vue---56-58、vue组件创建的三种方式

    黑马vue---56-58.vue组件创建的三种方式 一.总结 一句话总结: 不论是哪种方式创建出来的组件,组件的 template 属性指向的模板内容,必须有且只能有唯一的一个根元素 1.使用 Vu ...

  3. 【Java EE 学习 52】【Spring学习第四天】【Spring与JDBC】【JdbcTemplate创建的三种方式】【Spring事务管理】【事务中使用dbutils则回滚失败!!!??】

    一.JDBC编程特点 静态代码+动态变量=JDBC编程. 静态代码:比如所有的数据库连接池 都实现了DataSource接口,都实现了Connection接口. 动态变量:用户名.密码.连接的数据库. ...

  4. SpringBoot工程创建的三种方式

    一. 通过IDEA的spring Initializer创建 1. 打开创建项目面板 File->New->Project->Spring Initializr 2. 填写Maven ...

  5. wpf 创建动画三种方式

    动画类型 : 故事版,CompositionTarget,DispachTime 那么到此,三种动态创建动画的方法都已经详细介绍过了,大家可能会有种感觉,比较钟情于第一种WPF/Silverlight ...

  6. React: React组件创建的三种方式

    一.简介 在前面介绍的React组件知识中,对于组件的创建我只是用了其中某一种方式.其实,在2013年React诞生之初,对于React组件的创建,仅仅只有一种方式,也即createClass函数,在 ...

  7. 51、多线程创建的三种方式之实现Callable接口

    实现Callable接口创建线程 Callable接口是在jdk5版本中加入的,这个接口在java.util.concurrent包下面,与其他两种方式不同的地方在于使用Callable接口创建的线程 ...

  8. vue组件创建的三种方式

    1.使用Vue.extend创建全局的Vue组件 //1.1 使用vue.extend创建组件 var com1 = Vue.extend({ //通过template属性指定组件要展示的html结构 ...

  9. IOS第12天(1,UIViewController控制器的创建的 三种方式,和第一个view创建)

    *************HMAppDelegate.m中 @implementation HMAppDelegate - (BOOL)application:(UIApplication *)app ...

随机推荐

  1. sklearn集成支持向量机svm.SVC参数说明

    经常用到sklearn中的SVC函数,这里把文档中的参数翻译了一些,以备不时之需. 本身这个函数也是基于libsvm实现的,所以在参数设置上有很多相似的地方.(PS: libsvm中的二次规划问题的解 ...

  2. Angular(06)- 为什么数据变化,绑定的视图就会自动更新了?

    这里提一点,前端三大框架(Angular,React,Vue)的数据驱动来更新视图的原理,即 MVVM 的实现. 为什么数据发生变化,绑定的视图就会刷新了呢? 以下是我的个人理解,仅供参考: 在还是 ...

  3. How to use special characters in XML?

    https://dvteclipse.com/documentation/svlinter/How_to_use_special_characters_in_XML.3F.html Because X ...

  4. 十分钟 CODING DevOps 全链路体验

    近期 CODING 团队在 2019 KubeCon 大会上发布 DevOps 一站式解决方案:CODING 2.0.此次 CODING 全新上线了持续集成与制品库模块,通过自动化与标准化的方式来帮助 ...

  5. Windows和linux下的端口转发

    利用VPN,实现无公网IP或内网服务器的服务 @@@code netsh interface portproxy add v4tov4 listenport=8887 connectaddress=1 ...

  6. Zabbix-3.4简介及安装配置

    一.概述 1.为什么选择Zabbix? Zabbix是一款能够监控各种网络参数以及服务器健康性和完整性的软件.Zabbix使用灵活的通知机制,允许用户为几乎任何事件配置基于邮件的告警.这样可以快速反馈 ...

  7. Flink01

    1. 什么是Flink? 1.1 4代大数据计算引擎 第一代: MapReducer 批处理 Mapper, Reducer Hadoop的MapReducer将计算分为两个阶段, 分别为Map和Re ...

  8. Java面试准备基础篇_11.24

    Java类加载机制 Java内存模型JMM 为什么 Redis 单线程能支撑高并发? 高并发下的接口幂等性解决方案! 面试官问:平常你是怎么对 Java 服务进行调优的? JAVA虚拟机(JVM)六: ...

  9. MySQL常用SQL语句总结

    1.with rollup 可以实现在分组统计数据基础上再进行相同的统计 SELECT name, SUM(score) as score_count FROM  score GROUP BY nam ...

  10. PAT 1012 The Best Rank 排序

    To evaluate the performance of our first year CS majored students, we consider their grades of three ...