一、中介模型

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

    #!/usr/bin/env python #-*- coding:utf-8 -*- ############################ #File Name: pi.py #Author: ...

  2. PHP获得数组的交集与差集

    PHP获得数组的交集与差集 作者:简明现代魔法图书馆 发布时间:-- :: 次阅读 服务器君一共花费了218. ms进行了6次数据库查询,努力地为您提供了提供了这个页面. 数组的交集 array_in ...

  3. jdk8 Function

    例子 1: // 定义function Function<String, String> fun = parm -> { // 这里是定function中的逻辑 return Str ...

  4. 数据库设计(三)11 important database designing rules which I follow

    原文地址:https://www.codeproject.com/Articles/359654/important-database-designing-rules-which-I-fo 麻辣个

  5. nginx配置事例

    #user nobody; worker_processes 4; #error_log logs/error.log; #error_log logs/error.log notice; #erro ...

  6. c++封装的发邮件类CSendMail

    项目需要做发邮件的功能,在网上找了一下代码,比较出名的SMailer编译不过(把那个Base64的encode拉到MailSender中实现就能过,但我搞不懂原来出错的原因,就不想用),另外找到了一个 ...

  7. ASP.NET动态增加HTML元素的方法实例小结

    本文实例讲述了ASP.NET动态增加HTML元素的方法.分享给大家供大家参考,具体如下: 在使用asp.net进行web开发的时候页面中的<head></head>中的信息可以 ...

  8. python数据表的合并(python pandas join() 、merge()和concat()的用法)

    merage# pandas提供了一个类似于关系数据库的连接(join)操作的方法<Strong>merage</Strong>,可以根据一个或多个键将不同DataFrame中 ...

  9. poj 1322 Chocolate (概率dp)

    ///有c种不同颜色的巧克力.一个个的取.当发现有同样的颜色的就吃掉.去了n个后.到最后还剩m个的概率 ///dp[i][j]表示取了i个还剩j个的概率 ///当m+n为奇时,概率为0 # inclu ...

  10. select循环读取数据

    <select id="srType" name="srType" value="test"> <c:forEach va ...