关联对象参考

写在最前面——基础示例模型如下:

from django.db import models

class Blog(models.Model):
name = models.CharField(max_length=100)
tagline = models.TextField() def __str__(self): # __unicode__ on Python 2
return self.name class Author(models.Model):
name = models.CharField(max_length=200)
email = models.EmailField() def __str__(self): # __unicode__ on Python 2
return self.name class Entry(models.Model):
blog = models.ForeignKey(Blog, on_delete=models.CASCADE)
headline = models.CharField(max_length=255)
body_text = models.TextField()
pub_date = models.DateField()
mod_date = models.DateField()
authors = models.ManyToManyField(Author)
n_comments = models.IntegerField()
n_pingbacks = models.IntegerField()
rating = models.IntegerField() def __str__(self): # __unicode__ on Python 2
return self.headline
class RelatedManager

用在一对多或者多对多关系中的管理器。存在于以下两种情况:

  • ForeignKey外键关系的另一端:
from django.db import models

  class Reporter(models.Model):
# ...
pass class Article(models.Model):
reporter = models.ForeignKey(Reporter, on_delete=models.CASCADE)

下文的方法对于上面示例中的reporter.article_set管理器是有效的。

  • ManyToMany关系的两端:
class Topping(models.Model):
# ...
pass class Pizza(models.Model):
toppings = models.ManyToManyField(Topping)

下文的方法对于上面示例中的topping.pizza_set管理器和pizza.toppings管理器都是有效的。

add(*objs,bulk=True)

将指定模型对象加到相关对象集中。示例:

>>> b = Blog.objects.get(id=1)
>>> e = Entry.objects.get(id=234)
>>> b.entry_set.add(e) # Associates Entry e with Blog b.

在上面的示例中,外键关系的add()方法用QuerySet.update()来实施更新。这要求对象是已保存的。

当设置bulk=False时,则调用e.save()来实施更新。

当多对多关联对象使用add()方法时,并不调用save()方法,而是使用QuerySet.bulk_create()来创建关联。如果你在创建关联时需要执行一些自定义的逻辑,请查看m2m_changed

create(**kwargs)

创建一个新对象,保存并将它加入到关联对象集中。返回新创建的对象:

>>> b = Blog.objects.get(id=1)
>>> e = b.entry_set.create(
... headline='Hello',
... body_text='Hi',
... pub_date=datetime.date(2005, 1, 1)
... ) # 这里不必调用 e.save() -- 它已经被保存了。

相当于:

>>> b = Blog.objects.get(id=1)
>>> e = Entry(
... blog=b,
... headline='Hello',
... body_text='Hi',
... pub_date=datetime.date(2005, 1, 1)
... )
>>> e.save(force_insert=True)

注意,不需要为关联模型指定关键字参数。在上面的示例中,没有传入blog参数到create()方法`中,因为Django已经知道新Entry对象的blog字段应设置为b。

remove(*objs)

将指定的模型对象从关联对象集中移除:

>>> b = Blog.objects.get(id=1)
>>> e = Entry.objects.get(id=234)
>>> b.entry_set.remove(e) # Disassociates Entry e from Blog b.

add()类似,示例中调用了e.save()实施更新。而多对多关系使用remove()方法时,使用QuerySet.delete()删除关联。如果你在删除关联时需要执行一些自定义的逻辑,请查看m2m_changed

对于ForeignKey对象,只有null=True时本方法才有效。如果外键不允许为空,那么在关联到另一个模型前不能被删除。在上面的示例中,从b.entry_set()删除e相当于设置e.blog=None ,而由于blog的外键没有设置null=True,所以这是无效的。

对于外键对象,本方法接收bulk参数来控制怎么实施操作。如果为True (默认值),使用QuerySet.update() ;如果为False ,则每个单独的模型实例调用save()方法。这会触发pre_savepost_save信号,并会有性能开销。

clear()

移除关联对象集中的所有对象:

>>> b = Blog.objects.get(id=1)
>>> b.entry_set.clear()

注意,这并没有删除关联对象——只是消除了关联。

类似与remove() ,对于外键关系,只有null=True时,clear()才有效,它同样也接收bulk关键字参数。

set(objs, bulk=True, clear=False)

替换关联对象:

>>> new_list = [obj1, obj2, obj3]
>>> e.related_set.set(new_list)

本方法接收一个clear参数来控制操作方式。如果为False (默认值),先比较新旧对象集,在新对象集中没有的对象会用remove()从旧对象集中移除掉,然后只增加新旧对象不重叠的对象;如果为True ,则用clear()方法清楚所有旧对象集,然后一次性加入整个新对象集。

bulk参数会传入add()方法。

注意,由于set()是一个混合操作,它服从于竞争条件(race conditions)。例如,同时调用clear()add(),但是结果可能是新对象被添加到数据库中。

译者注:竞争条件

竞争条件指多个线程或者进程在读写一个共享数据时结果依赖于它们执行的相对时间的情形。

竞争条件发生在当多个进程或者线程在读写数据时,其最终的的结果依赖于多个进程的指令执行顺序。

例如:考虑下面的例子

假设两个进程P1和P2共享了变量a。在某一执行时刻,P1更新a为1,在另一时刻,P2更新a为2。

因此两个任务竞争地写变量a。在这个例子中,竞争的“失败者”(最后更新的进程)决定了变量a的最终值。

多个进程并发访问和操作同一数据且执行结果与访问的特定顺序有关,称为竞争条件。

注意

对所有种类的关联字段,add()create()remove()clear() ,和set()都会立即应用更改,不必在任何一端再调用save()

另外,如果使用的是多对多关系的媒介模型,add()create()remove()set()方法是无效的。

如果使用prefetch_related()add()remove()clear() ,和set()会清除吊缓存。

直接赋值

通过将一个新的可迭代对象赋值给关联对象集,可以批量替换掉旧的对象集:

>>> new_list = [obj1, obj2, obj3]
>>> e.related_set = new_list

如果外键关系设置了null=True ,那么再添加新列表之前,关联管理器将首先解除原有对象集中对象的关联。否则的话,新的列表将加入到原有的对象集。

以下1.10版中的用法已废弃:

>>> e.related_set.set([obj1, obj2, obj3])

Django-1.11中文文档——操作关联对象的更多相关文章

  1. Django 1.10中文文档-第一个应用Part2-模型和管理站点

    本教程继续Part1.我们将设置数据库,创建您的第一个模型,并快速介绍Django的自动生成的管理网站. 数据库设置 现在,编辑mysite/settings.py.它是一个用模块级别变量表示Djan ...

  2. Django 1.10中文文档-执行查询

    Django 1.10中文文档: https://github.com/jhao104/django-chinese-doc 只要创建好 数据模型, Django 会自动为生成一套数据库抽象的API, ...

  3. Django 1.10中文文档-聚合

    Django 数据库抽象API 描述了使用Django 查询来增删查改单个对象的方法. 然而,有时候你要获取的值需要根据一组对象聚合后才能得到. 这个主题指南描述了如何使用Django的查询来生成和返 ...

  4. Django 1.10中文文档-第一个应用Part7-自定义管理站点

    开发第一个Django应用,Part7 本教程上接Part6.将继续完成这个投票应用,本节将着重讲解如果用Django自动生成后台管理网站. 自定义管理表单 通过admin.site.register ...

  5. Django 1.10中文文档-第一个应用Part5-测试

    本教程上接教程Part4. 前面已经建立一个网页投票应用,现在将为它创建一些自动化测试. 自动化测试简介 什么是自动化测试 测试是检查你的代码是否正常运行的行为.测试也分为不同的级别.有些测试可能是用 ...

  6. Django 1.10中文文档-第一个应用Part3-视图和模板

    本教程上接Django 1.10中文文档-第一个应用Part2-模型和管理站点.我们将继续开发网页投票这个应用,主要讲如何创建一个对用户开放的界面. 概览 视图是Django应用中的一“类”网页,它通 ...

  7. Django 1.10中文文档—第一个Django应用Part1

    在本教程中,我们将引导您完成一个投票应用程序的创建,它包含下面两部分: 一个可以进行投票和查看结果的公开站点: 一个可以进行增删改查的后台admin管理界面: 我们假设你已经安装了Django.您可以 ...

  8. Django REST framework 中文文档

    Django REST framework介绍 现在前后端分离的架构设计越来越流行,业界甚至出现了API优先的趋势. 显然API开发已经成为后端程序员的必备技能了,那作为Python程序员特别是把Dj ...

  9. Django 1.10中文文档-第一个应用Part6-静态文件

    本教程上接Part5 .前面已经建立一个网页投票应用并且测试通过,现在主要讲述如何添加样式表和图片. 除由服务器生成的HTML文件外,网页应用一般还需要提供其它必要的文件——比如图片.JavaScri ...

随机推荐

  1. Angular写一个Form组件-TagInput

    前端开发少不了和表单打交道; Angular中, 提供了强大的表单的支持, 响应式表单(Reactive Form) 和 模板驱动的表单(Template-driven Form) 的双向数据流给我们 ...

  2. Codeforces 1364C - Ehab and Prefix MEXs

    题意:给1e5的数组a 保证 ai <= ai+1  ai<=i  求一个一样长的数组b 使得mex(b1,b2···bi) = ai QAQ:不知道为啥这1600分的题比赛时出不了 啊啊 ...

  3. K - Japan(线段树)

    Japan plans to welcome the ACM ICPC World Finals and a lot of roads must be built for the venue. Jap ...

  4. CodeCraft-20 (Div. 2) C. Primitive Primes (数学)

    题意:给你两个一元多项式\(f(x)\)和\(g(x)\),保证它们每一项的系数互质,让\(f(x)\)和\(g(x)\)相乘得到\(h(x)\),问\(h(x)\)是否有某一项系数不被\(p\)整除 ...

  5. Codeforces Round #658 (Div. 2) C2. Prefix Flip (Hard Version) (构造)

    题意:给你两个长度为\(n\)的01串\(s\)和\(t\),可以选择\(s\)的前几位,取反然后反转,保证\(s\)总能通过不超过\(2n\)的操作得到\(t\),输出变换总数,和每次变换的位置. ...

  6. C# 静态类 单例模式 对比

    公司的类都需要使用单例模式实现,这个可以节省资源,避免重复对象的生成.但是静态类也可以做到这一点,而且写起来更简洁,于是查阅相关资料,希望弄明白两者的差别. 1.单例模式可以在用到的时候初始化,而静态 ...

  7. 洛谷P1462-通往奥格瑞玛的道路-二分+最短路

    洛谷P1462-通往奥格瑞玛的道路 题目描述 在艾泽拉斯,有\(n\)个城市.编号为\(1,2,3,...,n\). 城市之间有\(m\)条双向的公路,连接着两个城市,从某个城市到另一个城市,会遭到联 ...

  8. 洛谷P1144-最短路计数-最短路变形

    洛谷P1144-最短路计数 题目描述: 给出一个\(N\)个顶点\(M\)条边的无向无权图,顶点编号为\(1-N\).问从顶点\(1\)开始,到其他每个点的最短路有几条. 思路: \(Dijkstra ...

  9. 实战交付一套dubbo微服务到k8s集群(6)之交付dubbo-monitor到K8S集群

    dubbo-monitor官方源码地址:https://github.com/Jeromefromcn/dubbo-monitor 1.下载dubbo-monitor源码 在运维主机(mfyxw50. ...

  10. 关于vmwaretools

    今天安装Ubuntu16.04-i386,vmware15.5,使用的快速安装,然后安装vmwaretools出现问题:无法复制粘贴,顶部管理"重新安装vmware-tools"选 ...