关联对象参考

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

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. 设计模式(五)——原型模式(加Spring框架源码分析)

    原型模式 1 克隆羊问题 现在有一只羊 tom,姓名为: tom, 年龄为:1,颜色为:白色,请编写程序创建和 tom 羊 属性完全相同的 10 只羊. 2 传统方式解决克隆羊问题 1) 思路分析(图 ...

  2. cartographer环境建立以及建图测试(详细级)

  3. SDNUOJ1016矩形合并

    传送门 题意: 给出n个矩形,把重合的矩形归成一个图形,问合并以后剩下几个图形 思路: 我开始想用dfs,但是发现不太行. 后来知道才是并查集 Orz 用一个结构体数组存矩形的左下角和右上角的坐标,再 ...

  4. 矩阵树定理(Kirchhoff || Laplace)初探——Part 1(无向图计数)

    必备知识: 高斯消元,图论基本知识(好像就这...(雾)) 这里是无向图部分,请不要走错场... 定义 我们将邻接矩阵定义为矩阵\(A(u,v)\),我想邻接矩阵就不用再多说了: 我们将每个点的度数矩 ...

  5. poj3757 Training little cats

    Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 11496   Accepted: 2815 Description Face ...

  6. Java中赋值常量的注意事项

    写在前面: 从网上学习的赋值规则 摘录自网络,标明出处 byte,short,int,long 比如 int a = 234; 此处的常量234类型默认是int,如果要将大的整数赋值给变量的话 必须 ...

  7. Codeforces Round #171 (Div. 2) B. Books (模拟队列)

    题意:有一组数,问子数组和最大不超过\(t\)的最多元素个数. 题解:用数组模拟队列,不断的往里面放,队列中的元素之和大于\(t\),就不断地从队头弹出直到满足条件,维护一个最大值即可. 代码: in ...

  8. 洛谷 P2880 [USACO07JAN]Balanced Lineup G (ST表模板)

    题意:给你一组数,询问\(q\)次,问所给区间内的最大值和最小值的差. 题解:经典RMQ问题,用st表维护两个数组分别记录最大值和最小值然后直接查询输出就好了 代码: int n,q; int a[N ...

  9. OkHttp Client Ignore certificate

    import okhttp3.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.net.ssl.*; i ...

  10. 爬虫——urllib.request包

    一.引用包 import urllib.request 二.常用方法 (1)urllib.request.urlretrieve(网址,本地文件存储地址):直接下载网页到本地 urllib.reque ...