关联对象参考

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

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. git的几种实用操作(合并代码与暂存复原代码)

    总述     git工具也用了很久,自己也写了几篇使用教程,今天继续给大家分享一些我工作中使用过的git操作. 1.git合并远程仓库的代码 2.git stash保存当前的修改 这两种情况大家应该都 ...

  2. PTA甲级—链表

    1032 Sharing (25分) 回顾了下链表的基本使用,这题就是判断两个链表是否有交叉点. 我最开始的做法就是用cnt[]记录每个节点的入度,发现入度为2的节点即为答案.后来发现这里忽略了两个链 ...

  3. hdu 4738 Caocao's Bridges(割边)

    题目链接 用tarjan求桥上的最小权值 #include<bits/stdc++.h> #define ll long long int using namespace std; inl ...

  4. Codeforces Beta Round #92 (Div. 2 Only) B. Permutations

    You are given n k-digit integers. You have to rearrange the digits in the integers so that the diffe ...

  5. 梨子带你刷burp练兵场(burp Academy) - 服务器篇 - Sql注入 - SQL injection UNION attack, determining the number of columns returned by the query

    目录 SQL injection UNION attack, determining the number of columns returned by the query SQL injection ...

  6. java中string,stringBuffer和StringBuider

    最近学习到StringBuffer,心中有好些疑问,搜索了一些关于String,StringBuffer,StringBuilder的东西,现在整理一下. 关于这三个类在字符串处理中的位置不言而喻,那 ...

  7. hlt instruction with IF=0

    mov AH, 2DH ;写时间. mov DH, 0 ;此时为0秒. int 21H ;写入系统. 遇到了这个问题. 原因是以及在保护模式了.保护模式下中断机制发生了很大的变化,原来的中断向量表被I ...

  8. xss 之herf输出

    首先查看下漏洞页面,发现输入的1111,  直接传参到herf 中, 查阅资料得知: 输出出现在a标签的href属性里面,可以使用javascript协议来执行js 查看源代码: if(isset($ ...

  9. web online code editor All In One

    web online code editor All In One 在线代码编辑器 Monaco Editor 摩纳哥编辑器 ️ 22.1k The Monaco Editor is the code ...

  10. RESTful 架构 && RESTful API

    RESTful 架构 && RESTful API REpresentational State Transfer (REST) 具象状态传输https://en.wikipedia. ...