关联对象参考

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

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. Pytest(8)parametrize参数化

    前言 当某个接口中的一个字段,里面规定的范围为1-5,你5个数字都要单独写一条测试用例,就太麻烦了,这个时候可以使用pytest.mark.parametrize装饰器可以实现测试用例参数化. 官方示 ...

  2. Codeforces Round #575 (Div. 3) F. K-th Path

    传送门 题意: 这道题把我看得懵懵的(不敢相信),其实就是给你n个点和m条边(无向图),你要找出来任意两点之间的的最短距离,然后再从其中找出来第k个最小值 题解: 正常思维就是floyd多源最短路算法 ...

  3. KMP && Manacher && 扩展KMP整理

    KMP算法: kmp示例代码: void cal_next(char *str, int *next, int len) { next[0] = -1;//next[0]初始化为-1,-1表示不存在相 ...

  4. Codeforces Round #479 (Div. 3) C. Less or Equal (排序,贪心)

    题意:有一个长度为\(n\)的序列,要求在\([1,10^9]\)中找一个\(x\),使得序列中恰好\(k\)个数满足\(\le x\).如果找不到\(x\),输出\(-1\). 题解:先对这个序列排 ...

  5. Linux-字符处理命令

    目录 1.sort(排序) 2.uniq(不相邻的两行重复不会去除) 3.cut(取列,截取字段) 4.wc(统计行.单词.字符数) 1.sort(排序) 选项: -t # 指定分隔符 -k # 指定 ...

  6. 服务注册与发现-Eureka (高可用设计)

    什么是高可用 部署需要考虑的是什么: 1.系统遇到单点失效问题,如何能够快速切换到其他节点完成任务 2.如何应对网络故障,即系统如何设计成"故障开放型"(expecting fai ...

  7. java笔试中创建String对象的思考

    题目是这样的下面那些生成新的String对象() A . String  s = new String(); B . String  s = new String("A"); C. ...

  8. ARM汇编指令-STMFD/LDMFD

    根据调用规则ATPCS,程序一般都使用FD(FullDescending)类型的数据栈(满栈),那么对立的就由空栈类型的数据栈.空栈是指SP操作完后指向的地址空间是未使用的,反之满栈就是SP指向的地址 ...

  9. vue 自动注册全局组件

    vue 自动注册全局组件 vue 注册全局组件的方式 const plugins = { install(Vue) { const requireComponent = require.context ...

  10. CSS ? Layout Module : CSS 布局模型

    1 1 1 https://www.w3.org/TR/css-grid-1/ CSS Grid Layout Module Level 1 W3C Working Draft, 19 May 201 ...