Django 1.10 中文文档——3.2.2 查询操作making queries

2017年1月14日凌晨,周有光上天死去,前一天,他刚刚过完了112寒暑之生辰。

迎大家看我之私家网站《刘江的博客和学科》:www.liujiangblog.com

2018年1月14日,谷歌搜索封面的Google不见了,而是用插画的款式表现了Google
的汉语名:谷歌,用来纪念周有光这员汉语拼音之大诞辰112周年。

# 主要分享Python 及Django教程以及相关的博客

即时号通过晚清、军阀混战、民国时期、新中国四代的前辈,在外身上产生众多底价签:沈从文的连襟算一个、合肥四姊妹中张允和的爱人终于一个、“汉语拼音之大”算一个,经济学家也毕竟一个。

3.2.2 查询操作

6.15段包含有模型相关的API解释。
后的情节据悉如下的一个博客应用模型:

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)
    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

周有光的一生,早年折腾经济,50春之后将拼音改革,八竿子打不交联合的从,都为外摊上了。

3.2.2.1 创建对象

如若模型是mysite/blog/models.py文件中,那么创建对象的道如下:

>>> from blog.models import Blog
>>> b = Blog(name='Beatles Blog', tagline='All the latest Beatles news.')
>>> b.save()

于后台,这会运作一长SQL的INSERT语句。如果你免形的调用save()方法,Django不会立刻用欠操作反映到数据库被。save()方法无回来值,它可领一些额外的参数。

比方想如果一行代码完成点的操作,请动creat()方法,它可以简单save的手续:

b = Blog.objects.create(name='Beatles Blog', tagline='All the latest Beatles news.')

有人将周有光的生平分为三只号:50岁以前是银行家、50春及85春是语言文字学家、85夏以后是思考下(主要是敢言)。

3.2.2.2 保存对象

应用save()方法,保存对数据库内就起目标的改。例如:如果既有b5对象在数据库内:

>>> b5.name = 'New name'
>>> b5.save()

在后台,这会运作一长达SQL的UPDATE语句。如果你莫显得的调用save()方法,Django不会立刻将拖欠操作反映到数据库被。

实质上,我不过重的价签是,他是一个重情重义的好老公。

封存外键和多针对几近字段

保存一个外键字段和封存普通字段没什么区别,只是只要注意值的门类要正确。下面的事例,有一个Entry的实例entry和一个Blog的实例cheese_blog,然后把cheese_blog作为值赋给了entry的blog属性,最后调用save方法开展封存。

>>> from blog.models import Entry
>>> entry = Entry.objects.get(pk=1)
>>> cheese_blog = Blog.objects.get(name="Cheddar Talk")
>>> entry.blog = cheese_blog
>>> entry.save()

差不多针对性大多字段的保存稍微有硌分别,需要调用一个add()方法,而非是直接被属性赋值,但其不待调用save方法。如下例所示:

>>> from blog.models import Author
>>> joe = Author.objects.create(name="Joe")
>>> entry.authors.add(joe)

在一行语句内,同时加上多独对象到差不多针对性几近之字段,如下所示:

>>> john = Author.objects.create(name="John")
>>> paul = Author.objects.create(name="Paul")
>>> george = Author.objects.create(name="George")
>>> ringo = Author.objects.create(name="Ringo")
>>> entry.authors.add(john, paul, george, ringo)

倘若你指定要加加了错类型的靶子,Django会抛来非常。

01

3.2.2.3 检索对象

想念要于数据库内搜索对象,你待根据模型类,通过管理器(Manager)构造一个询问结果集(QuerySet)。

每个QuerySet代表有些数据库对象的会师。它可蕴涵零个、一个或者多单过滤器(filters)。Filters缩小查询结果的界定。在SQL语法被,一个QuerySet相当给一个SELECT语句,而filter则相当给WHERE或者LIMIT一好像的子句。

透过模型的Manager获得QuerySet,每个模型起码存有一个Manager,默认情况下,它让誉为“objects”,可以经过模型类直接调用它,但无能够通过模型类的实例调用它,以此实现“表级别”操作及“记录级别”操作的要挟分离。如下所示:

>>> Blog.objects
<django.db.models.manager.Manager object at ...>
>>> b = Blog(name='Foo', tagline='Bar')
>>> b.objects
Traceback:
...
AttributeError: "Manager isn't accessible via Blog instances."

1906年1月13日,周有光生被江苏常州青果巷,原名周耀平。

搜索所有目标

以all()方法,可以抱有张表的有所记录。

>>> all_entries = Entry.objects.all()

1916年,周有光10寒暑经常,全家迁居苏州。

过滤器检索对象

来2单主意可以用来过滤QuerySet的结果,分别是:

filter(kwargs):返回一个冲指定参数查询出来的QuerySet
exclude(
kwargs):返回除了因指定参数查询出来结果的QuerySet
其中,**kwargs参数的格式必须是Django设置的一些字段格式。

例如:

Entry.objects.filter(pub_date__year=2006)

它同样于:

Entry.objects.all().filter(pub_date__year=2006)

链式过滤

filter和exclude的结果依然如故是个QuerySet,因此它们可以连续被filter和exclude,这就算形成了链式过滤:

>>> Entry.objects.filter(
...     headline__startswith='What'
... ).exclude(
...     pub_date__gte=datetime.date.today()
... ).filter(
...     pub_date__gte=datetime(2005, 1, 30)
... )

(译者:这里需要专注的凡,当在进行过关系之链式过滤时,结果也许与而想象的未一致,参考下面的过多值关系查询)

深受过滤的QuerySets都是绝无仅有的

列一样涂鸦过滤,你还见面取得一个簇新的QuerySet,它同前面的QuerySet没有其余关系,可以了独立的为保存,使用和用。例如:

>>> q1 = Entry.objects.filter(headline__startswith="What")
>>> q2 = q1.exclude(pub_date__gte=datetime.date.today())
>>> q3 = q1.filter(pub_date__gte=datetime.date.today())

事例中的q2和q3虽然由于q1得来,是q1的子集,但是还是自主存在的。同样q1也非会见面临q2和q3的熏陶。

QuerySets都是懈怠的

一个创办QuerySets的动作不会见马上导致其他的数据库行为。你得堆栈所有的filter动作一整天,Django不会运行任何实际的数据库查询动作,直到QuerySets被交给(evaluated)。

简而言之即是,只有遇到一些特定的操作,Django才会将兼具的操作体现到数据库内,否则她只是保存在内存和Django的范畴中。这是平等栽提高数据库查询效率,减少操作次数之优化规划。看下的例子:

>>> q = Entry.objects.filter(headline__startswith="What")
>>> q = q.filter(pub_date__lte=datetime.date.today())
>>> q = q.exclude(body_text__icontains="food")
>>> print(q)

点的例子,看起执行了3不好数据库访问,实际上只是于print语句子时实行了1不行造访。通常状态,QuerySets的觅不会见马上执行实际的数据库查询操作,直到出现类似print的求,也便是所谓的evaluated。具有有怎样操作会触发evaluated,请查看6.15.8章节。

1918年,入常州高级中学(江苏省这第五中学)预科,一年后正式升入中学。

找寻单一对象

filter方法始终返回的是QuerySets,那恐惧光发一个目标符合过滤条件,返回的呢是含一个对象的QuerySets。

若是你规定你的索只会博得一个目标,那么你得运用Manager的get()方法来一直归这个目标。

>>> one_entry = Entry.objects.get(pk=1)

以get方法被您得用任何filter方法的查询参数,一模子一样。

顾:使用get()方法及行使filter()方法然后经[0]的法门分片,有着不同之地方。看似两者都是获得单一对象。但是,如果以询问时不曾匹配到对象,那么get()方法以摒弃来DoesNotExist异常。这个可怜是模型类的一个特性,在地方的事例中,如果非有主键为1之Entry对象,那么Django将抛出Entry.DoesNotExist异常。

恍如地,在运get()方法查询时,如果结果跳1独,则会扔来MultipleObjectsReturned异常,这个充分与否是模型类的一个性。

1923年,他考入上海圣约翰大学主修经济与语言学。这所院校是神州顶早的行大学,顾维钧,林语堂、宋子文等还是当这个学校成长起来的。

其它QuerySet方法

查阅6.15.8落更多不同之QuerySet方法有关信息

按照记载,进入学校的第一天,周有光就收取校方的通知,要求每位领到一摆放姓名卡,在上头用打印机打上每个人的姓名的罗马配并写法,周有光发现用字母建档相对而言,中文并无极端好。

QuerySet以限制

以类Python对列表进行切开的措施可针对QuerySet进行界定取值。它一定给SQL语句被的LIMIT和OFFSET子句。参考下面的例证:

>>> Entry.objects.all()[:5]      # 返回前5个对象
>>> Entry.objects.all()[5:10]    # 返回第6个到第10个对象

专注:不支持负索引!例如 Entry.objects.all()[-1]凡无允许的

平常情况,切片操作会返回一个初的QuerySet,并且不见面吃及时执行。但是生一个不等,那就是是指定步长的下,查询操作会立刻在数据库内履,如下:

>>> Entry.objects.all()[:10:2]

使一旦抱单一的对象要无是一个列表(例如,SELECT foo FROM bar LIMIT
1),可以概括地动索引而休是片。例如,下面的话语返回数据库被因题目排序后的第一久Entry:

>>> Entry.objects.order_by('headline')[0]

它们一定给:

>>> Entry.objects.order_by('headline')[0:1].get()

顾:如果没有匹配到对象,那么首先栽方法会抛来IndexError异常,而第二种植方法会弃来DoesNotExist异常。

也就是说在用get和片的当儿,要留意查询结果的素个数。

此后,周有光就起对拼音感兴趣,选修了语言学。

字段查询

字段查询其实就算是filter()、exclude()和get()方法的最主要字参数。
该主干格式是:field__lookuptype=value,注意其中凡双下划线。
例如:

>>> Entry.objects.filter(pub_date__lte='2006-01-01')
# 相当于:
SELECT * FROM blog_entry WHERE pub_date <= '2006-01-01';

内部的field必须是范中定义之filed之一。但是有一个例外,那就是ForeignKey字段,你可以为夫增长一个“_id”后缀(单下划线)。这种景象下键值是外键模型的主键原生值。例如:

>>> Entry.objects.filter(blog_id=4)

如若你传递了一个野鸡的键值,查询函数会抛出TypeError异常。
Django的数据库API支持20几近栽查询类型,完整的参考手册在6.15节,下面介绍部分常用之:

exact:

默认类型。如果您无提供查询类型,或者重点字参数不带有一个双下划线,那么查询类型就是者默认的exact。

>>> Entry.objects.get(headline__exact="Cat bites dog")
# 相当于
# SELECT ... WHERE headline = 'Cat bites dog';
# 下面两个相当
>>> Blog.objects.get(id__exact=14)  # Explicit form
>>> Blog.objects.get(id=14)         # __exact is implied

iexact:

莫分轻重缓急写。

>>> Blog.objects.get(name__iexact="beatles blog")
# 匹配"Beatles Blog", "beatles blog",甚至"BeAtlES blOG".

contains:

意味着包含的意思!大小写敏感!

Entry.objects.get(headline__contains='Lennon')
# 相当于
# SELECT ... WHERE headline LIKE '%Lennon%';
# 匹配'Today Lennon honored',但不匹配'today lennon honored'

icontains:

contains的大大小小写不灵敏模式。

startswith和endswith

盖什么开和以什么最后。大小写敏感!

istartswith和iendswith是免区分轻重缓急写的模式。

1933年,27春之周有光与了一个民间组织“拉丁化新文字运动”,发表了有关于语言文字方面的章,笔名为周有光,自此便正式使用此名字了。

越关系查询

Django提供了强劲又直观的不二法门化解过关联的查询,它在后台自动执行包含JOIN的SQL语句。要过某个关联,只待用关联的范字段名称,并以对下划线分隔,直至你想要之字段(可以链式跨越,无限跨度)。例如:

# 返回所有Blog的name为'Beatles Blog'的Entry对象
# 一定要注意,返回的是Entry对象,而不是Blog对象。
# objects前面用的是哪个class,返回的就是哪个class的对象。
>>> Entry.objects.filter(blog__name='Beatles Blog')

相反的相同,如果一旦引用一个反向关联,只待利用模型的略微写名!

# 获取所有的Blog对象,前提是它所关联的Entry的headline包含'Lennon'
>>> Blog.objects.filter(entry__headline__contains='Lennon')

而您于系列关联中开展过滤而内部有中间型没有满足过滤条件的值,Django将把它当一个空的(所有的价都也NULL)但是合法的靶子,不会见扔来另外特别要错。例如,在底下的过滤器中:

Blog.objects.filter(entry__authors__name='Lennon')

设若Entry中尚无关联任何的author,那么它将当其没有name,而休见面坐没author
引发一个荒谬。通常,这是于吻合逻辑的处理方式。唯一可能于你困惑的是当您利用isnull的当儿:

Blog.objects.filter(entry__authors__name__isnull=True)

即时将回来Blog对象,它关系的entry对象的author字段的name字段为空,以及Entry对象的author字段为空。如果您切莫待后人,你可如此描写:

Blog.objects.filter(entry__authors__isnull=False,entry__authors__name__isnull=True)

超越多值关系查询

极致中心的filter和exclude的显要字参数就发生一个,这种情形很好掌握。但是当重点字参数有差不多个,且是跨外键或者多对多之景象下,那么就比较复杂,让人口迷惑了。我们看下面的例子:

Blog.objects.filter(entry__headline__contains='Lennon', entry__pub_date__year=2008)

立即是一个超过外键的,两个过滤参数的询问。此时我们清楚两单参数之间属于-与“and”的关联,也就是说,过滤出来的BLog对象对应的entry对象要以满足上面两单标准。这点异常好掌握。但是,看下面的用法:

Blog.objects.filter(entry__headline__contains='Lennon').filter(entry__pub_date__year=2008)

把个别只参数拆起来,放在两独filter调用里面,按照我们眼前说罢之链式过滤,这个结果应和方的事例一样。可实际,它不雷同,Django在这种状况下,将鲜个filter之间的涉计划为-或“or”,这当成让人头疼。
差不多对大多涉及下的多值查询以及外键foreignkey的事态同样。

唯独,更头疼的来了,exclude的国策设计的以与filter不一致!

Blog.objects.exclude(entry__headline__contains='Lennon',entry__pub_date__year=2008,)

立会去掉headline中含“Lennon”的Entry和当2008年发表的Entry,中间是一个-和“or”的涉!

这就是说只要清除以满足上面两独规范的对象,该怎么处置也?看下面:

Blog.objects.exclude(
entry=Entry.objects.filter(
    headline__contains='Lennon',
    pub_date__year=2008,
),
)

(译者:有没出十分坑爹的痛感?所以,建议以遇见过关系之多值查询时,尽量利用Q查询)

1940年周有光于纽约办事中间以花大量底时间研究这个语言文字学。

下F表达式引用模型的字段

到目前为止的例子中,我们都是以模型字段与常量进行较。但是,如果您想用模型的一个字段与与一个模的另外一个字段进行较该怎么惩罚?

使用Django提供的F表达式!

像,为了找寻comments数目多于pingbacks数目的Entry,可以组织一个F()对象来引用pingback
数目,并于询问中采取该F()对象:

>>> from django.db.models import F
>>> Entry.objects.filter(n_comments__gt=F('n_pingbacks'))

Django支持对F()对象进行加、减、乘、除、取模以及幂运算等算术操作。两独操作数可以是常数和另外F()对象。例如查找comments数目比pingbacks两倍增还要多之Entry,我们得这么形容:

>>> Entry.objects.filter(n_comments__gt=F('n_pingbacks') * 2)

为查询rating比pingback和comment数目总和要有些之Entry,我们可以这么写:

>>> Entry.objects.filter(rating__lt=F('n_comments') + F('n_pingbacks'))

你还得当F()中采用对下蛋划线来展开跨表查询。例如,查询author的讳和blog名字同样之Entry:

>>> Entry.objects.filter(authors__name=F('blog__name'))

对此date和date/time字段,还得加要减去一个timedelta对象。下面的例子将回到发布时跨3天后吃改的所有Entry:

>>> from datetime import timedelta
>>> Entry.objects.filter(mod_date__gt=F('pub_date') + timedelta(days=3))

F()对象还支持.bitand()和.bitor()两栽位操作,例如:

>>> F('somefield').bitand(16)

只是,这些都是外的兴趣爱好而已,业余工作。

主键的霎时查询办法:pk

pk就是primary
key的缩写。通常状态下,一个模型的主键为“id”,所以下面三只报告句子的功效等同:

>>> Blog.objects.get(id__exact=14) # Explicit form
>>> Blog.objects.get(id=14) # __exact is implied
>>> Blog.objects.get(pk=14) # pk implies id__exact

好一并其他类型的参数:

# Get blogs entries with id 1, 4 and 7
>>> Blog.objects.filter(pk__in=[1,4,7])
# Get all blog entries with id > 14
>>> Blog.objects.filter(pk__gt=14)

足跨表操作:

>>> Entry.objects.filter(blog__id__exact=3) 
>>> Entry.objects.filter(blog__id=3) 
>>> Entry.objects.filter(blog__pk=3)

(译者:当主键不是id的时,请留意了!)

1955年前,周有光的主业仍是事半功倍、金融。

机关转义百分符号和下划线

于原生SQL语句中%标志来破例的打算。Django帮你活动的转义了百分符号和下划线,你可与一般性字符一样使用它们,如下所示:

>>> Entry.objects.filter(headline__contains='%')
# 它和下面的一样
# SELECT ... WHERE headline LIKE '%\%%';

02

缓存和查询集合

每个QuerySet都含一个缓存,用于减少针对数据库的实际操作。

对新创办的QuerySet,它的缓存是空的。当QuerySet第一潮受付后,数据库执行实际的查询操作,Django会把询问的结果保存在QuerySet的苏存内,随后的对于该QuerySet的交由将用这个缓存的数额。

设想迅速的施用查询结果,降低数据库负载,你必善于以缓存。看下的例子,这会导致2次其实的数据库操作,加倍数据库的负荷,同时由于时日不一之题目,可能于点滴浅操作间数据为删或涂改或者添加,导致污染数据的题目:

>>> print([e.headline for e in Entry.objects.all()])
>>> print([e.pub_date for e in Entry.objects.all()])

为避免上面的题材,好之应用办法如下,这才发相同不良实际上的询问操作,并且维持了数额的一致性:

>>> queryset = Entry.objects.all()
>>> print([p.headline for p in queryset]) # 提交查询
>>> print([p.pub_date for p in queryset]) # 重用查询缓存

何时休会见受缓存

起有操作不会见缓存QuerySet,例如切片和目录。这即造成这些操作没有缓存可用,每次都见面履实际的数据库查询操作。例如:

>>> queryset = Entry.objects.all()
>>> print queryset[5] # 查询数据库
>>> print queryset[5] # 再次查询数据库

然,如果已经遍历过一切QuerySet,那么就算相当给缓存过,后续之操作则会动缓存,例如:

>>> queryset = Entry.objects.all()
>>> [entry for entry in queryset] # 查询数据库
>>> print queryset[5] # 使用缓存
>>> print queryset[5] # 使用缓存

脚的这些操作都将全部历QuerySet并建立缓存:

>>> [entry for entry in queryset]
>>> bool(queryset)
>>> entry in queryset
>>> list(queryset)

顾:简单的由印QuerySet并无见面树立缓存,因为__repr__()调用只回去全部查询集的一个片。

周有光是名字让更多的口认识,并非他的经济标准、也非是拼音对华之奉献。虽说这片个内容之孝敬特别,但是对于多数人数而言,是产生接触小偏门的。

3.2.2.4 使用Q对象进行复杂查询

普普通通filter函数里的标准化且是“and”逻辑,如果你想实现“or”逻辑怎么处置?用Q查询!

Q来自django.db.models.Q,用于封装关键字参数的集聚,可以当作首要字参数用于filter、exclude和get等函数。
例如:

from django.db.models import Q
Q(question__startswith='What')

足使用“&”或者“|”或“~”来组合Q对象,分别代表与或非逻辑。它以赶回一个新的Q对象。

Q(question__startswith='Who')|Q(question__startswith='What')
# 这相当于:
# WHERE question LIKE 'Who%' OR question LIKE 'What%'
Q(question__startswith='Who') | ~Q(pub_date__year=2005)

公吗可以这样使用,默认情况下,以逗号分隔的都意味着AND关系:

Poll.objects.get(
Q(question__startswith='Who'),
Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6))
)
# 它相当于
# SELECT * from polls WHERE question LIKE 'Who%'
AND (pub_date = '2005-05-02' OR pub_date = '2005-05-06')

当重要字参数与Q对象成使用时,Q对象要放在面前,如下例子:

Poll.objects.get(
Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6)),question__startswith='Who',)

倘若主要字参数放在Q对象的面前,则会报错。
(译者:关于Q对象还有再尖端的利用办法)

外也世人认识,是以他娶了一个誉为张允和的家。

3.2.2.5 比较对象

万一比较单薄独模型实例,只待运用python提供的双等号比较适合就好了。在后台,其实正如的是片只实例的主键的值。
下两种植方式是相同的:

>>> some_entry == other_entry
>>> some_entry.id == other_entry.id

一旦模型的主键不称“id”也尚无干,后台总是会使正确的主键名字进行比,例如,如果一个模的主键的名是“name”,那么下面是齐的:

>>> some_obj == other_obj
>>> some_obj.name == other_obj.name

张允同是合肥四姊妹被的亚,叶圣陶为是羡慕说谁娶了就四单姐妹福气太好了。

3.2.2.6 删除对象

剔除对象下的凡delete()方法。该方式将回到给删去对象的毕竟数量及一个字典,字典包含了每种被剔除对象的品种和欠类型的多少。如下所示:

>>> e.delete()
(1, {'weblog.Entry': 1})

足批量抹。每个QuerySet都发生一个delete()方法,它能够去除该QuerySet的有着成员。例如:

>>> Entry.objects.filter(pub_date__year=2005).delete()
(5, {'webapp.Entry': 5})

待专注的凡,有或未是各个一个对象的delete方法都给实施。如果你改写了delete方法,为了保目标吃删,你不能不手动迭代QuerySet进行逐项删除操作。

当Django 删除一个对象时,它默认使用SQL的ON DELETE
CASCADE约束,也就是说,任何发生外键指向要删减对象的靶子将联合被删除。例如:

b = Blog.objects.get(pk=1)
# 下面的动作将删除该条Blog和所有的它关联的Entry对象
b.delete()

这种级联的行可经的ForeignKey的on_delete参数自定义。

小心,delete()是绝无仅有无于管理器上展露出来的法。这是刻意设计之一个安然无恙机制,用来防止你不意地请类似Entry.objects.delete()的动作,而不慎删除了所有的条款。如果您真想去所有的靶子,你不能不旗帜鲜明地伸手一个净的查询集,像下这样:

Entry.objects.all().delete()

说起来,搬家到苏州的周有光及张允及算打小之相知,而且,周有光的妹子周俊人是张允和乐益女被之校友。

3.2.2.7 复制模型实例

虽然没放的计用于复制模型的实例,但还是老大易创建一个初的实例并拿原实例的有所字段都拷贝过来。最简单易行的方式是以本来实例的pk设置也None,这会创一个初的实例copy。示例如下:

blog = Blog(name='My blog', tagline='Blogging is easy')
blog.save() # blog.pk == 1
#
blog.pk = None
blog.save() # blog.pk == 2

不过在应用持续的当儿,情况会转移得复杂,如果生下一个Blog的子类:

class ThemeBlog(Blog):
theme = models.CharField(max_length=200)
#
django_blog = ThemeBlog(name='Django', tagline='Django is easy', theme='python')
django_blog.save() # django_blog.pk == 3

依据继承的行事体制,你必同时将pk和id设为None:

django_blog.pk = None
django_blog.id = None
django_blog.save() # django_blog.pk == 4

上面的措施都未曾提到关联对象。如果你想复制关系,你必手动多写一些代码,像下这样:

entry = Entry.objects.all()[0] # 一些原始的entry对象
old_authors = entry.authors.all()
entry.pk = None
entry.save()
entry.authors = old_authors # 保存新的多对多关系

简单贱离将近,张允同常常串门找周俊人玩儿,时日同等漫长就对准新生的夫妻就熟悉了。

3.2.2.8 批量翻新目标

行使update()方法可以批量为QuerySet中具备的目标进行翻新操作。

# 更新所有2007年发布的entry的headline
Entry.objects.filter(pub_date__year=2007).update(headline='Everything is the same')

君仅仅堪对一般字段和ForeignKey字段使用此方式。若一旦更新一个常备字段,只待提供一个新的经常反复值。若一旦创新ForeignKey字段,需安装新值为你想对的初模型实例。例如:

>>> b = Blog.objects.get(pk=1)
# 修改所有的Entry,让他们都属于b
>>> Entry.objects.all().update(blog=b)

update方法会受当下实施,并返回操作匹配到的实践的数量(有或无顶要翻新的履的数目,因为有些行或早已发此新值了)。唯一的束缚是:只能看同摆设数库表。你可因涉字段进行过滤,但您不得不更新模型主表的字段。例如:

>>> b = Blog.objects.get(pk=1)
# Update all the headlines belonging to this Blog.
>>> Entry.objects.select_related().filter(blog=b).update(headline='Everything is the same')

设若留心的凡update()方法会直接换成为一个SQL语句,并立即批量尽。它不见面运行模型的save()方法,或者发pre_save或post_save信号(调用save()方法发生)或者服从auto_now字段选项。如果您想保留QuerySet中的每个条目并包每个实例的save()方法还让调用,你无需要用另外特别之函数来拍卖。只需要迭代它们并调用save()方法:

for item in my_queryset:
    item.save()

update方法好配合F表达式。这对批量翻新同一型中之一只字段特别发因此。例如增加Blog中每个Entry的pingback个数:

>>> Entry.objects.all().update(n_pingbacks=F('n_pingbacks') + 1)

但是,与filter和exclude子句被之F()对象不同,在update中而免得以使用F()对象开展跨表操作,你不过堪引用在更新的范的字段。如果您尝试使用F()对象引入另外一张表的字段,将摒弃来FieldError异常:

# THIS WILL RAISE A FieldError
>>> Entry.objects.update(headline=F('blog__name'))

自拿周有光同张允同结婚前分为四只级次,他们谈恋爱是慢性进行的,细水长流,不像郁达夫、徐志摩等丁用力量过盛。

3.2.2.9 关联的对象

动本节一开始之范,一个Entry对象e可以由此blog属性e.blog获取涉及的Blog对象。反过来,Blog对象b可以经过entry_set属性b.entry_set.all()访问和它涉及的所有Entry对象。

1925年-1926年是第一只级次,周有光对张允和来好感阶段。

一对多(外键)

刚巧往查询
直白通过圆点加属性,访问外键对象:

>>> e = Entry.objects.get(id=2)
>>> e.blog # 返回关联的Blog对象

只要留心的凡,对外键的改动,必须调用save方法开展封存,例如:

>>> e = Entry.objects.get(id=2)
>>> e.blog = some_blog
>>> e.save()

设若一个外键字段设置有null=True属性,那么好透过让该字段赋值为None的道移除外键值:

>>> e = Entry.objects.get(id=2)
>>> e.blog = None
>>> e.save() # "UPDATE blog_entry SET blog_id = NULL ...;"

于第一坏对一个外键关系进行正向访问的时刻,关系对象会为缓存。随后对平外键关系对象的走访会以这缓存,例如:

>>> e = Entry.objects.get(id=2)
>>> print(e.blog)  # 访问数据库,获取实际数据
>>> print(e.blog)  # 不会访问数据库,直接使用缓存的版本

请注意QuerySet的select_related()方法会递归地预填充所有的等同针对性几近干及缓存中。例如:

>>> e = Entry.objects.select_related().get(id=2)
>>> print(e.blog)  # 不会访问数据库,直接使用缓存
>>> print(e.blog)  # 不会访问数据库,直接使用缓存

反向查询

要一个型有ForeignKey,那么该ForeignKey所对的外键模型的实例可以透过一个管理器进行反为查询,返回源模型的有实例。默认情况下,这个管理器的名吧FOO_set,其中FOO是根源模型的有点写名称。该管理器返回的查询集可以就此前提到的方法进行过滤与操作。

>>> b = Blog.objects.get(id=1)
>>> b.entry_set.all() # Returns all Entry objects related to Blog.
# b.entry_set is a Manager that returns QuerySets.
>>> b.entry_set.filter(headline__contains='Lennon')
>>> b.entry_set.count()

若可当ForeignKey字段的定义着,通过设置related_name来重写FOO_set的名。举例说明,如果你修改Entry模型blog
= ForeignKey(Blog, on_delete=models.CASCADE,
related_name=’entries’),那么地方的事例会成下面的指南:

>>> b = Blog.objects.get(id=1)
>>> b.entries.all() # Returns all Entry objects related to Blog.
# b.entries is a Manager that returns QuerySets.
>>> b.entries.filter(headline__contains='Lennon')
>>> b.entries.count()

使用从定义的反向管理器

默认情况下,用于反为关系的RelatedManager是拖欠模型默认管理器的子类。如果你想为一个询问指定一个例外的管理器,你可利用下的语法:

from django.db import models

class Entry(models.Model):
    #...
    objects = models.Manager()  # 默认管理器
    entries = EntryManager()    # 自定义管理器

b = Blog.objects.get(id=1)
b.entry_set(manager='entries').all()

自然,指定的自定义反往管理器也可调用它的自定义方法:

b.entry_set(manager='entries').is_published()

拍卖涉及对象的任何措施

除去在前面“检索对象”一节被定义之QuerySet方法之外,ForeignKey管理器还生其他方法用于拍卖涉及的目标集合。下面是每个方法的不外乎,完整的细节可以以论及6.15.4被找到。

add(obj1, obj2, …):添加指定的模子对象到关系的对象集中。
create(**kwargs):创建一个新的对象,将她保存并雄居事关的目标集中。返回新创的靶子。
remove(obj1, obj2, …):从涉嫌的目标集中删除指定的型对象。
clear():清空关联的目标集。
set(objs):重置关联的靶子集。

设使一次性吃涉嫌的靶子集赋值,使用set()方法,并叫她赋值一个可迭代的目标集合或者一个主键值的列表。例如:

b = Blog.objects.get(id=1)
b.entry_set.set([e1, e2])

以斯事例中,e1和e2可以是共同体的Entry实例,也足以是整数的主键值。

如果clear()方法可用,那么以用可迭代对象吃的成员添加到集合中之前,将自entry_set中除去所有曾经在的目标。如果clear()方法不可用,那么将直添加可迭代对象吃的成员如不见面去除所有已在的目标。

当时节被的每个反向操作都以随即以数据库内实行。所有的多、创建与去操作为将这自动地保留至数据库内。

每当上海求学的周有光有空就掉苏州老家,同学里串串门,有接触好感,仅限于此。

多对多

差不多对几近干的两岸都见面自动获得访问另一样端的API。这些API的干活方式以及前面提到的“反朝”一对大多关系之用法一样。

唯的分在属性之称呼:定义ManyToManyField的型使用该字段的性名称,而“反为”模型使用源模型的微写名称加上’_set’
(和均等对几近干一样)。

e = Entry.objects.get(id=3)
e.authors.all() # Returns all Author objects for this Entry.
e.authors.count()
e.authors.filter(name__contains='John')
#
a = Author.objects.get(id=5)
a.entry_set.all() # Returns all Entry objects for this Author.

跟外键字段中一律,在多针对几近之字段中呢可指定related_name名。
(译者注:在一个模型中,如果存在多只外键或多对准大多的干,必须让她们分别长不同之related_name,用于反朝查询)

当时同样年,徐志摩以追求陆小曼、陆小曼以发离婚,民国当下啊专程红火。

一对一

一定颇类似多对同样涉嫌,可以简单的经过模型的习性访问关联的模型。

class EntryDetail(models.Model):
    entry = models.OneToOneField(Entry, on_delete=models.CASCADE)
    details = models.TextField()
#
ed = EntryDetail.objects.get(id=2)
ed.entry # Returns the related Entry object.

不同之处在于反往查询的时。一针对性同样关系面临之涉及模型同样有一个管理器对象,但是该管理器表示一个单一的靶子要不是目标的集:

e = Entry.objects.get(id=2)
e.entrydetail # 返回关联的EntryDetail对象

假定没有对象赋值给这涉及,Django将抛出一个DoesNotExist异常。
足叫反朝关系进行赋值,方法以及正向的关联一样:

e.entrydetail = ed

1927年-1928年凡是第二号,周有光开始追求有点他三秋的张允和,属于懵懂阶段。

反向关联是怎样实现的?

一些ORM框架需要你以论及之两端都进展定义。Django的开发者认为这违反了DRY
(Don’t Repeat Yourself)原则,所以在Django中你不过待以同一端进行定义。

那么这是怎落实的啊?因为当论及的模型类没有受加载之前,一个模型类向不亮堂有什么样类与她关系。

答案在app
registry!在Django启动的时光,它见面导入所有INSTALLED_APPS中之运用以及每个应用中之模型模块。每创建一个初的模子时,Django会自动抬高反向的干及拥有涉的范。如果涉嫌的范还不曾导入,Django将保存关联的记录并于提到的模子导入时加上这些关乎。

由此原因,将模型所在的使用还定义在INSTALLED_APPS的利用列表中尽管显得特别重大。否则,反向关联将不可知正确工作。

1927年周有光毕业了,在上海教,而张允和也试到了上海的学府,本来就熟悉的少数独人口当异乡越来越熟悉起来。

由此关系对象开展询问

关联关联对象的查询及正常值的字段查询仍平等的平整。当您指定询问需要相当的价值时,你可以使一个目标实例或者目标的主键值。

如,如果你产生一个id=5之Blog对象b,下面的老三独查询将凡一心一致的:

Entry.objects.filter(blog=b) # 使用对象实例
Entry.objects.filter(blog=b.id) # 使用实例的id
Entry.objects.filter(blog=5) # 直接使用id

女大十八变,这时的张允和,已是一个小姑娘了,书香世家的孩子气质优雅至极,清淡有余,明眸善睐。

3.2.2.10 调用原生SQL语句

一旦你发现用编制的Django查询语句极复杂,你可以回归到手工编制SQL语句。Django对于编写原生的SQL查询有那么些选择,参见3.2.6节执行原生的SQL查询。

终极,需要小心的凡Django的多寡库层只是一个数据库接口。你得用其他的工具、编程语言还是数据库框架来走访数据库,Django没有强制指定你不要是下其的之一意义要模块。

周有光开始喜欢这个邻家妹子了。

当即员邻居妹子对周有光不极端排斥,有相同碰好感。

而是姑娘家家的或者处于羞怯阶段,没有许,而且张允以及为躲周有才,从东宿舍藏及外来宿舍,请管理员帮忙撒谎说其未在,周有光每一样糟糕来探寻张允及连失败而归。

1929年-1932年凡第三只级次,表达认同阶段。

有情人终成眷属,但是也未是胜利的。

周有光非常坚持。

1929年,周有光及常州长期出差,与张允和中往来主要是经过信件,感情逐渐升温。

1932年,因为战火关系,张允以及至了杭州,两个发情人在杭州终确定了涉。

03

规定关系及了谈婚论嫁的时段,周有光开始动摇与顾虑:“我好干净,怕不可知为您幸福。”

周有光早干嘛了?等女儿答应了,就从头撤出,这是恋爱之战术?

搞不清楚。

张允与磨了扳平封10张张的长信,中心思想是美满是一旦协调失去创造的,女人一旦独立,不指老公。

1933年4月30日,周有光及张允及于上海开办婚礼。张允以及凡合肥四姐妹被率先个婚的。

成家后,周有光在高等学校教学、兼职银行工作;张允及单教一边做编辑副刊;平静的婚姻生活又迎来了新的分子。

1934年4月20日,他们的崽诞生,取名周晓平,又平等年,女儿出生,取名小禾。

抗日战争爆发后,他们带动在些许独孩子开始挺逃亡。

1941年,小禾六春因患夭折。

1942年,儿子周晓平又陡让流弹击中,内脏被由来六单洞,幸好解救过来了。

有数赖意外周有光都为工作不以身边,张允同一个家里扛起了全方位家,非常勿爱。

刚巧使她好说之,命运为了锻炼自己,把最为难之题都为自身一个丁。

生性乐观的张允和、豁达的周有光,除了爱,性格与三观也许是夫妻长期保持的重要。

04

战争结束后,搞经济之周有光为集团安排及美国学,随后张允和带路儿子一起错过矣美国。

1949年,回国到了上海,在复旦教经济学。

1953年底“三反五反”运动里张允和受下了岗,就在爱人照看周有光一家老小,这样叫周有光得以安心钻研汉语言事业。

归根结底这是外的爱慕,更是副业。

1955年,组织调周有单独到京城,参加制定汉语拼音方案,任中国文字改革委员会跟国家语言文字工作委员会研究员、第一研究室负责人,被誉为:“汉语拼音之大”。

当三年之时日外,周有光深入语言学与文字学的钻研,确定拼音方案,并于1958年正规宣布。

这次调整为周有光避免了上海经济界的反右运动,对私家是福,对国家也是福。

但,始终不曾藏身了文化大革命。

1969年为放逐至宁夏平罗“五七干校”劳动,这无异年,周有光63年份,这无异于累就是2年。

他深受张允与通信,他想不开自己就等同代都距离不上马干校,无法回到北京,这样的想太漫长了,他认为张允同不该受耽搁累。

张允及扭转了一如既往句子,那我每个月还受你寄予眼药水,再添加几块巧克力糖。

周有光回忆:“到了都继,一直顶自妻子死,我们每日上午10沾喝茶,有的上吧喝咖啡。喝茶、喝咖啡的下,我们片个举杯齐眉,这自然有平等碰好游戏,更是我们相互敬重的一律种植表达。”

05

张允以及回忆其和周有光在上海率先次握手,她说:“当自身的平光手被外抓住的上,我便把内心交给了外。”

80寒暑的张允和,每天以仔细梳妆、认真过戴,还要周有光评价一番。

2002年8月14日,张允及平静辞世,享年93载,这对准周有光是一个沉重的打击。

他们共同走过了70年,相濡以沫,从未红了体面,坚持动了终身。

外购入了沙发,夜深人静不再回卧室,每天都弯腿因为于沙发上。

一半年晚,他拿张允和的遗作整理出版,算是不过好之思念。

2005年,100心虚夏之周有光提出“终身教育,百秋自学”并出版了《百东新稿》、104春秋出版了《朝闻道集》、105寒暑出版了《拾贝集》、108年出版了《周有光文集》、110年份经常以产生《逝年如度——周有光百年口述》出版。

2015年1月22日,他们的小子周晓平因患有亡。

立马世界上点滴个最好亲之人即使这样离开了。

2017年1月13日,过了112春秋大寿的周有光,次日凌晨以患有亡,享年112年。

06

周有光生前最为烦别人叫他“拼音的大”,所有的荣于外看来还是空泛。

她们来同样摆放两丁的婚纱照。

周有光写的是:人得几近情人不老。

张允与增补及同样句子:多情至老情更好。

立马是他们之柔情、他们一生最好的见证。

更平淡、经历跌宕的一代、经历了分手的惨痛,没有轰轰烈烈,没有海誓山盟,依然相守,这才是人世间最得意的情意。

文/蓝胖2018.01.14

民国时期的“合肥四姊妹”在科学界声名卓著,四各夫婿各起别致,成就了华近代史上之同截佳话。蓝胖笔下的季姊妹:

张允和:张家四姐妹的二姐姐传奇,一切都是最好之布

张兆与:这等同好吃见沈从文,不知是幸亏还是背?

张充和:看见自己、爱上协调,世间不再颠沛流离

张元及:张家四姐妹的大姐,32年度晚婚嫁人,她一生之故事只有昆曲和夫


此文写了4独小时,阅读大约6分钟,你独自待花费1秒钟,点亮下面的“喜欢”,就只是藏内容——

最为好的上虚度光阴 最特别之年份洗尽铅华

蓝胖,肥而不腻的一个70年晚老男人 喜欢研究管厘头的历史

出“民国系列”“古代层层”“外国系列”“诗词故事系列”等人物历史故事

炒炒煎炸有预期、有趣、有寓意的故事烩

转载以及版权合作关系pub@jianshu.com

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图