一、中介模型

  我们之前学习图书管理系统时,设计了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. EM5-PE2B

    1. vocabulary once adv. 一次,曾经 They cocktailed once every week. He once lived in shanghai. twice adv ...

  2. 初识PowerShell

    一.简介 Windows PowerShell 是微软公司为Windows环境所开发的壳程序(shell)及脚本语言技术,采用的是命令行界面.这项全新的技术提供了丰富的控制与自动化的系统管理能力.之前 ...

  3. ORACLE / PLSQL 插入或更新数据的几种方式

    第一种,直接用values 插入 ---日期需要用TO_DATE操作 INSERT INTO EMP (EMPNO,ENAME ,JOB,MGR, HIREDATE , SAL ,COMM, DEPT ...

  4. ECMall中Widgets模式的布局引擎

    自己做过框架的人,可能都会思考一个问题,模板引擎需要什么特性? Widgets模式,很多系统中都有出现,但对于纯开发人员,不管前端或后台人员来说,都觉得稍微麻烦了一点.因为他将界面硬生生的拆分出了很多 ...

  5. 【Mac + Android】之Android Studio 环境搭建,AVD模拟器运行(包括:命令行运行AVD,并且Genymotion模拟器插件配置运行)

    目录: 前提.Mac环境下手动配置Android SDK 一. Android Studio下载及配置 二.AVD模拟器配置运行 扩展:命令行运行AVD模拟器 三.在Android Studio 中配 ...

  6. python入门(四):标准输出和文件读写

    Python输出 1.表达式语句 str(): 函数返回一个用户易读的表达形式,可以使用 str.format() 函数来格式化输出值. repr(): 产生一个解释器易读的表达形式. 2.print ...

  7. Database Designer

    DBDesigner http://fabforce.net/dbdesigner4/index.php DB Designer Fork http://sourceforge.net/project ...

  8. 简单的php基于curl的反向代理程序

    起因: 经理:需要实现一个反向代理? 我:  简单,nginx分分钟配置好. 经理:嗯?没有nginx? 我: nodejs也行啊,网上有例子分分钟搞定. 经理:嗯?只有虚拟主机,只能上传php程序? ...

  9. linux连接mysql命令

    连接MYSQL: 格式: mysql -h主机地址 -u用户名 -p用户密码 1.例1:连接到本机上的MYSQL 找到mysql的安装目录,一般可以直接键入命令mysql -uroot -p,回车后提 ...

  10. elasticsearch.net search入门使用指南中文版

    原文:http://edu.dmeiyang.com/book/nestusing.html elasticsearch.net为什么会有两个客户端? Elasticsearch.Net是一个非常底层 ...