一、中介模型

  我们之前学习图书管理系统时,设计了Publish、Book、Author、AuthorDetail这样几张表,其中Book表和Author表是多对多关系,处理类似这样简单的多对多关系时,使用标准的ManyToManyField就可以了。但是,有时你可能需要关联数据到两个模型之间的关系上。

  例如,有这样一个应用,它记录音乐家所属的音乐小组。我们可以用一个ManyToManyField 表示小组和成员之间的多对多关系。但是,有时你可能想知道更多成员关系的细节,比如成员是何时加入小组的。

  对于这些情况,Django 允许你指定一个中介模型来定义多对多关系。 你可以将其他字段放在中介模型里面。原模型的ManyToManyField 字段将使用through 参数指向中介模型。对于上面的音乐小组的例子,代码如下:

  from django.db import models

  class Person(models.Model):
  name = models.CharField(max_length=128)   def __str__(self): # __unicode__ on Python 2
   return self.name   class Group(models.Model):
  name = models.CharField(max_length=128)
  members = models.ManyToManyField("Person", through='Membership')   def __str__(self): # __unicode__ on Python 2
  return self.name   class Membership(models.Model):
  person = models.ForeignKey("Person", on_delete=models.CASCADE)
  group = models.ForeignKey("Group", on_delete=models.CASCADE)
  date_joined = models.DateField()
  invite_reason = models.CharField(max_length=64)

  既然你已经设置好ManyToManyField 来使用中介模型(在这个例子中就是Membership),接下来你要开始创建多对多关系。你要做的就是创建中介模型的实例:

  >>> ringo = Person.objects.create(name="Ringo Starr")   # 创建一个音乐家ringo
  >>> paul = Person.objects.create(name="Paul McCartney") # 创建一个音乐家paul
  >>> beatles = Group.objects.create(name="The Beatles") # 创建一个音乐小组beatles
  >>> m1 = Membership(person=ringo, group=beatles,
  ... date_joined=date(1962, 8, 16),
  ... invite_reason="Needed a new drummer.") # 创建一个中介模型的实例
  >>> m1.save()
  >>> beatles.members.all() # 多对多的正向查询语法
  [<Person: Ringo Starr>]
  >>> ringo.group_set.all() # 多对多的反向查询语法
  [<Group: The Beatles>]
  >>> m2 = Membership.objects.create(person=paul, group=beatles,
  ... date_joined=date(1960, 8, 1),
  ... invite_reason="Wanted to form a band.") # 创建一个中介模型的实例
  >>> beatles.members.all() # 多对多的正向查询语法
  [<Person: Ringo Starr>, <Person: Paul McCartney>]

  注意:与普通的多对多字段不同,不能使用add、create和赋值语句(比如,beatles.members = [...])来创建关系:

  # THIS WILL NOT WORK
  >>> beatles.members.add(john)
  # NEITHER WILL THIS
  >>> beatles.members.create(name="George Harrison")
  # AND NEITHER WILL THIS
  >>> beatles.members = [john, paul, ringo, george]

  为什么不能这样做?这是因为你不能只创建 Person和 Group之间的关联关系,你还要指定 Membership模型中所需要的所有信息(比如date_joined和invite_reason);而简单的add、create 和赋值语句是做不到这一点的。所以它们不能在使用中介模型的多对多关系中使用。此时,唯一的办法就是创建中介模型的实例。

  remove()方法被禁用也是出于同样的原因。但是clear()方法却是可用的。它可以清空某个实例所有的多对多关系:

  # Beatles have broken up
  >>> beatles.members.clear()
  # Note that this deletes the intermediate model instances
  >>> Membership.objects.all()
  []

Django - 回顾(2)- 中介模型的更多相关文章

  1. Django QuerySet和中介模型

    笔记如下 一.QuerySet QuerySet是什么? 类似列表里边存着对象 只和ORM有关系 from app01.models import Book def qDemo(request): b ...

  2. Django进阶之QuerySet和中介模型

    QuerySet QuerySet是查询集,就是传到服务器上的url里面的查询内容.其形态类似于Python的列表,列表中的元素是QuerySet对象.支持大部分列表的内置方法. 可切片 QueryS ...

  3. Django框架 之 ORM中介模型

    Django框架 之 ORM中介模型 中介模型 处理类似搭配 pizza 和 topping 这样简单的多对多关系时,使用标准的ManyToManyField  就可以了.但是,有时你可能需要关联数据 ...

  4. django中介模型,CBV模型,及logging日志配制

    1.中介模型 中介模型,这个是在我们创建表格时,多对多添加的时候应用到的,通过制定ManyToManyField字段中的through参数来定义,为两者的关系新建一个中介class 为什么会产生这个中 ...

  5. Django【第26篇】:中介模型以及优化查询以及CBV模式

    中介模型以及优化查询以及CBV模式 一.中介模型:多对多添加的时候用到中介模型 自己创建的第三张表就属于是中介模型 class Article(models.Model): ''' 文章表 ''' t ...

  6. Orm之中介模型

    什么是中介模型 中介模型针对的是ManyToMany(多对多)的时候第三张表的问题, 中介模型其实指的就是我们不通过Django创建第三张表,如果自己不创建第三张表,而是由django给我们创建,那就 ...

  7. 中介模型以及优化查询以及CBV模式

    一.中介模型:多对多添加的时候用到中介模型 自己创建的第三张表就属于是中介模型 class Article(models.Model): ''' 文章表 ''' title = models.Char ...

  8. 中介模型,cbv视图,和查询优化

    中介模型: 处理类似搭配 pizza 和 topping 这样简单的多对多关系时,使用标准的ManyToManyField  就可以了.但是,有时你可能需要关联数据到两个模型之间的关系上. 例如,有这 ...

  9. Django-model进阶(中介模型,查询优化,extra,整体插入)

    QuerySet 可切片 使用Python 的切片语法来限制查询集记录的数目 .它等同于SQL 的LIMIT 和OFFSET 子句. ? 1 >>> Entry.objects.al ...

随机推荐

  1. python学习之strip()

    定义: Python strip() 方法用于移除字符串头尾指定的字符(默认为空格). 语法: str.strip([chars]); 返回值: 返回移除字符串头尾指定的字符生成的新字符串. 例子: ...

  2. Linux编程之判断磁盘空间大小

    一.引言 在开发过程中,经常会碰到这样的情况,在往指定目录下拷贝文件时,需要考虑到磁盘空间的大小是否足够来决定什么时候暂停自己的程序 二.用的函数 <sys/statfs.h> int s ...

  3. js中对小数取整

    js中对小数取整的函数,需要的朋友可以参考下.   1.丢弃小数部分,保留整数部分 js:parseInt(7/2) 2.向上取整,有小数就整数部分加1 js: Math.ceil(7/2) 3,四舍 ...

  4. LeetCode 145 Binary Tree Postorder Traversal(二叉树的兴许遍历)+(二叉树、迭代)

    翻译 给定一个二叉树.返回其兴许遍历的节点的值. 比如: 给定二叉树为 {1. #, 2, 3} 1 \ 2 / 3 返回 [3, 2, 1] 备注:用递归是微不足道的,你能够用迭代来完毕它吗? 原文 ...

  5. Nginx+PHP-FPM优化技巧总结

    php-fpm的安装很简单,参见PHP(PHP-FPM)手动编译安装.下面主要讨论下如何提高Nginx+Php-fpm的性能.   1.Unix域Socket通信   之前简单介绍过Unix Doma ...

  6. Linux增加用户并赋予权限

    1.添加用户,首先用adduser命令添加一个普通用户,命令如下: #adduser tommy //添加一个名为tommy的用户#passwd tommy   //修改密码Changing pass ...

  7. 安装第三方模块时遇到Python version 2.7 required, which was not found

    ## script to register Python 2.0 or later for use with win32all# and other extensions that require P ...

  8. 利用JMeter的beanshell进行接口的加密处理

    最近项目中在做http协议的接口测试,其中接口请求报文数据有个字段值需要用到加密后的签名,即出于网络传输过程中,对数据安全的考虑,要对请求的数据进行特定的处理(加密),再进行请求. 刚开始由于项目赶进 ...

  9. 第一百四十一节,JavaScript,封装库--DOM加载

    JavaScript,封装库--DOM加载 DOM加载,跨浏览器封装DOM加载,当网页文档结构加载完毕后执行函数,不等待图片音频视频等文件加载完毕 /** dom_jia_zai()函数,DOM页面加 ...

  10. PDF解析。。。

    解析出PDF中的文字.用项目名称作Key取对应的值.. 正则匹配 .....:..\n