多对多三种创建方式

全自动

  • ManyToManyField(to=)
  • 优点: 无须自己创建多对多关系表, 支持orm跨表查询, 支持add, set, remove, clear方法
  • 不足: 表的扩展性较差
class Book(models.Model):
name = models.CharField(max_length=255)
# 自动创建多对多关系表
authors = models.ManyToManyField(to='Author') class Author(models.Model):
name = models.CharField(max_length=255)

纯手撸

  • 优点: 字段完全由自己定义
  • 不足: 不支持orm跨表查询, 不支持add, set, remove, clear方法
class Book(models.Model):
name = models.CharField(max_length=255) class Author(models.Model):
name = models.CharField(max_length=255) # 手动创建多对多关系表
class Book2Author(models.Model):
book = models.ForeignKey(to='Book')
author = models.ForeignKey(to='Author')
create_time = models.DateTimeField(auto_now=True)

半自动(推荐)

  • 半自动其实是在手动创建和自动创建的基础上, 利用 ManyToManyField() 字段, 内部维护关系

    • through='Book2Author' 该参数表示通过张表来建立表关系
    • through_fields=('book', 'authors') 该参数表示通过括号内的两个字段维护关系, 以便支持orm跨表查询
  • 优点: 可以任意添加和修改关系表中的字段, 支持orm跨表查询

  • 不足: 不支持add, set, remove, clear方法

  • 注意: 在哪一张表中创建多对多外键字段, 则through_fields传入的第一个参数就是该张表关联的字段


class Book(models.Model):
name = models.CharField(max_length=255)
# 半自动创建多对多关系表
authors = models.ManyToManyField(to='Author', through='Book2Author', through_fields=('book', 'authors')) class Author(models.Model):
name = models.CharField(max_length=255) class Book2Author(models.Model):
book = models.ForeignKey(to='Book')
author = models.ForeignKey(to='Author')
create_time = models.DateTimeField(auto_now=True)

form组件

校验数据

  • 导入: from django import forms
  • 自定义一个类 , 添加字段, 设置字段的限制条件
  • form_obj=MyForm(data) 传入一个待校验的字典数据, 实例化对象
  • form_obj.is_valid() 校验传入的数据是否符合字段的限制条件
  • form_obj.errors 返回一个字典, 存放不符合条件的字段以及错误信息
  • forms.cleaned_data 返回一个字典, 存放符合条件的字段和对应的数据
  • 默认所有的字段都必须传值, 不能少传, 多传的会被忽略
from django import forms

class MyForm(forms.Form):
# 用户名的长度不能超过10字符, 不能少于3个字符
username = forms.CharField(max_length=10, min_length=3)
# 密码位数不能小于六位
password = forms.CharField(min_length=6)
# 邮箱需要符合有邮箱格式
email = forms.EmailField() # 在测试文件运行下面的代码
# 需要校验的数据
data = {'username': 'bigb', 'password': '12345', 'email': '123.com'}
# 1.传入需要校验的数据, 实例化对象
form_obj = views.MyForm(data) # 2.is_valid() 判断数据是否符合条件
print(form_obj.is_valid()) # 3.errors 查看错误信息
print(form_obj.errors)
'''
{'password': ['Ensure this value has at least 6 characters (it has 5).'],
'email': ['Enter a valid email address.']}
''' # 4.cleaned_data 查看符合条件的数据
print(form_obj.cleaned_data) # {'username': 'bigb'} # 5.少传数据
data = {'username': 'bigb', 'password': '123456'}
form_obj = views.MyForm(data)
form_obj.is_valid()
Out[11]: False
form_obj.errors
Out[12]:
{'email': ['This field is required.']}

渲染标签

  • forms组件只会渲染输入标签, 不会渲染提交标签
  • {{ form_obj.as_p }}
  • {{form_obj.username.label}} 拿到 username 字段的字段名(文本)
  • {{form_obj.username}} 拿到 username 对应的input框
  • {% for form in form_obj %} --- {{form.label}} {{form}}
  • 给字段添加label参数, 可以自定义label的值, 默认是等于字段名
class MyForm(forms.Form):
# 用户名的长度不能超过10字符, 不能少于3个字符
username = forms.CharField(max_length=10, min_length=3, label='用户名')
# 密码位数不能小于六位
password = forms.CharField(min_length=6)
# 邮箱需要符合有邮箱格式
email = forms.EmailField() def index(request):
# 1.先生成一个空的form_obj
form_obj = MyForm()
# 2. 将form_obj发送到html文件
return render(request, 'index.html', locals())
<body>
<h1>forms组件渲染标签</h1> {{ form_obj.as_p }}
{{ form_obj.as_table}}
{{ form_obj.as_ul}} <input type="submit">
</body> <body>
<h1>forms组件渲染标签</h1> <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> <input type="submit">
</body> <!--推荐使用-->
<body>
<h1>forms组件渲染标签</h1> {% for form in form_obj %}
<p>{{ form.label }}{{ form }}</p>
{% endfor %} <input type="submit">
</body>

展示错误信息

  • 在form表单标签中加入属性 : novalidation 来取消前端校验

  • {{form.errors}} 可以拿到校验后的错误信息, 是一个列表, 在前端渲染成 ul 标签, 因此: {{form.errors.0}}

  • 字段的 error_massages={} 参数用来自定义报错信息

    • required: 不能为空
    • max_length: 最大长度
    • min_length: 最小长度
    • invalid: 格式错误
class MyForm(forms.Form):
# 用户名的长度不能超过10字符, 不能少于3个字符
username = forms.CharField(max_length=10, min_length=3, label='用户名',
error_messages={
'required': '用户名不能为空',
'max_length': '长度不能超过10个字符',
'min_length': '长度不能小于3个字符'
})
# 密码位数不能小于六位
password = forms.CharField(min_length=6, label='密码',
error_messages={
'required': '密码不能为空',
'min_length': '密码长度不能少于6位'
})
# 邮箱需要符合有邮箱格式
email = forms.EmailField(label='邮箱', error_messages={
'required': '邮箱不能为空',
'invalid': '邮箱格式错误'
}) def index(request):
# 1.先生成一个空的form_obj
form_obj = MyForm()
# 2. 将form_obj发送到html文件 if request.method == 'POST':
form_obj = MyForm(request.POST) return render(request, 'index.html', locals())
<form action="" method="post" novalidate>
{% for form in form_obj %}
<p>
{{ form.label }}{{ form }}
<span>{{ form.errors.0 }}</span>
</p>
{% endfor %}
<input type="submit">
</form>

validators校验器

  • Regexvalidator :通过正则表达式完成数据的校验

  • validators=[RegexValidator('正则表达式', '错误提示信息')]

phone = forms.CharField(label='手机号码', validators=[
RegexValidator(r'^(1[3-9])\d{9}$', '请输入正确的手机号码!')])

钩子函数

  • 钩子函数是对数据的最后一道校验
  • 在我们自定义的类下面创建
  • self.add_error('字段名', '错误信息') 给某个字段添加错误信息
  • 局部钩子函数返回校验字段
  • 全局钩子函数返回 self.cleaned_data
# 局部钩子函数, 校验用户名中不能包含特殊字符
def clean_username(self):
username = self.cleaned_data.get('username')
forbidden_char = r'\'/!@#$%^&*()_+|}{":>?<'
for i in forbidden_char:
if i in username:
self.add_error('username', '用户名中不能包含特殊符号!')
return username # 函数名用到什么字段, 就返回什么字段 # 全局钩子函数, 校验密码和确认密码是否一致
def clean(self):
confirm_password = self.cleaned_data.get('confirm_password')
password = self.cleaned_data.get('password') if confirm_password != password:
self.add_error('confirm_password', '密码输入不一致!') return self.cleaned_data # 函数名(全局)用到什么字段, 就返回什么字段

补充

  • initial 参数设置默认值

  • required=Flase 设置该字段可为空

  • label 参数设置input框对应的提示信息

  • widget参数可以设置input标签的type参数和属性

  • widget=forms.widgets.PasswordInput()

  • widget=forms.widgetds.TextInput({'class': 'form-control c1 c2', 'username':'bigb})

Django 09的更多相关文章

  1. Django 09 博客小案例

    Django 09 博客小案例 urls.py from django.urls import path from . import views urlpatterns = [ path('index ...

  2. Windows7WithSP1/TeamFoundationServer2012update4/SQLServer2012

    [Info   @09:03:33.737] ====================================================================[Info   @ ...

  3. django 报错Reverse for 'detail' with keyword arguments '{'pk': '2'}' not found. 1 pattern(s) tried: ['$post/(?P<pk>[0-9]+)/$']

    Django报错:Reverse for 'detail' with keyword arguments '{'pk': '2'}' not found. 1 pattern(s) tried: [' ...

  4. Django框架09 /ajax、crsf、settings导入

    Django框架09 /ajax.crsf.settings导入 目录 Django框架09 /ajax.crsf.settings导入 1. ajax概述 2. ajax应用 3. ajax上传文件 ...

  5. Django 2.0 学习(09):Django 静态文件(样式和背景图片)

    应用的定制化:静态文件 首先,在polls目录中创建一个名叫static的目录.Django会在该目录里面查找静态文件,类似于Django在polls/template目录下查找模板文件. Djang ...

  6. 09 - Django应用第六步

    1 自定义页面 在项目中, 肯定不会只是显示单纯的HTML文件, 我们可能还需要JS, CSS, 图片等 这些文件就被称为静态文件(starIc files) 在小的项目中, 可能静态文件比较少, 但 ...

  7. 09 Django组件之用户认证组件

    没有学习Django认证组件之前使用装饰器方法 from django.shortcuts import render, HttpResponse, redirect from app01.MyFor ...

  8. Django-中间件-csrf扩展请求伪造拦截中间件-Django Auth模块使用-效仿 django 中间件配置实现功能插拔式效果-09

    目录 昨日补充:将自己写的 login_auth 装饰装在 CBV 上 django 中间件 django 请求生命周期 ***** 默认中间件及其大概方法组成 中间件的执行顺序 自定义中间件探究不同 ...

  9. 09.Django基础七之Ajax

    一 Ajax简介 1.简介 AJAX(Asynchronous Javascript And XML)翻译成中文就是"异步的Javascript和XML".即使用Javascrip ...

随机推荐

  1. PHP导出成PDF你用哪个插件

    准备工作 首先查询了相关的类库,有FPDF,zendPDF,TcPDF等等.首先看了下先选择了FPDF,可以说除了中文字符以外没有什么问题,中文乱码而且看了下最新版本没有很好的解决方案,所以只能放弃. ...

  2. pdf2eps implement

    Well, I used the command pdftops in the LaTeX distribution such as MiKTeX/TeXLive/CTex to implement ...

  3. 领扣(LeetCode)删除链表中的节点 个人题解

    请编写一个函数,使其可以删除某个链表中给定的(非末尾)节点,你将只被给定要求被删除的节点. 现有一个链表 -- head = [4,5,1,9],它可以表示为: 4 -> 5 -> 1 - ...

  4. 调用RESTful GET方法

    package restclient; import java.io.BufferedReader; import java.io.IOException; import java.io.InputS ...

  5. 拎壶学python3-----(5)python之格式化输出

    一.格式化输入可以减少代码开发量如下是格式化输出: 上边的%是什么意思呢?%是一个占位符,s代表字符串的类型. 二.我们看下边的例子 看使用%d %i的用法. %d %i 这种格式化只能用数字来填补占 ...

  6. vue常用指令总结

    一.vue指令 官网解释 指令 (Directives) 是带有 v- 前缀的特殊特性.指令特性的值预期是单个 JavaScript 表达式 (v-for 是例外情况).指令的职责是,当表达式的值改变 ...

  7. tcp和udp的网络编程(发送消息及回复)

    一.UDP  无连接的  高效的  基于数据报的  不可靠 的连接 主要的应用场景: 需要资源少,网络情况稳定的内网,或者对于丢包不敏感的应用,比如 DHCP 就是基于 UDP 协议的.不需要一对一沟 ...

  8. JAVA _____Scanner用法

    今天就来说一说Scanner用法,以前我在学C的时候记得第一天学的是很普遍的HelloWord的输出,JAVA中的输出是这样子的, public class ScannerWriter { publi ...

  9. Lab6:进程的调度

    CPU调度 从就绪队列中挑选下一个占用CPU运行的进程,从多个可用CPU中挑选就绪进程可使用的CPU资源 调度策略 比较调度算法的准则 CPU使用率 吞吐量 周转时间 就绪等待时间 响应时间 吞吐量与 ...

  10. Scala函数式编程(四)函数式的数据结构 上

    这次来说说函数式的数据结构是什么样子的,本章会先用一个list来举例子说明,最后给出一个Tree数据结构的练习,放在公众号里面,练习里面给出了基本的结构,但代码是空缺的需要补上,此外还有预留的test ...