您的位置:澳门新葡萄京最大平台 > 动作小游戏 > 中文文档

中文文档

发布时间:2019-11-04 03:36编辑:动作小游戏浏览(117)

    应接我们访谈作者的个体网站《刘江(英文名:liú jiāng卡塔尔国的博客和科目》:www.liujiangblog.com

    # 首要分享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
    

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

    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会抛出相当。

    3.2.2.3 检索对象

    想要从数据库内搜索对象,你须要基于模型类,通过微型机(Manager卡塔 尔(英语:State of Qatar)构造一个询问结果集(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."
    
    探求全部指标

    利用all()方法,能够博得某张表的具备记录。

    >>> all_entries = Entry.objects.all()
    
    过滤器检索对象

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

    (译者:这里须求专一的是,当在进展跨关系的链式过滤时,结果只怕和您想象的不平等,参谋下边包车型客车跨多值关系查询卡塔 尔(英语:State of Qatar)

    被过滤的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章节。

    搜寻单生龙活虎对象

    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相当,那一个特别也是模型类的多个性能。

    其它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()方法的首要性字参数。
    其主导格式是:田野__lookuptype=value,注意在那之中是双下划线。
    例如:

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

    此中的田野先生必得是模型中定义的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是不区分抑扬顿挫写的情势。

    超越关系查询

    Django提供了强大而且直观的点子消除超越关联的询问,它在后台自动施行包罗JOIN的SQL语句。要超出某些关联,只需选拔关联的模子字段名称,并使用双下划线分隔,直至你想要的字段(能够链式赶上,Infiniti跨度卡塔尔。例如:

    # 返回所有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卡塔 尔(英语:State of Qatar)不过合法的对象,不会抛出其它极度或不当。例如,在底下的过滤器中:

    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和在二〇一〇年发布的Entry,中间是贰个-和“or”的涉嫌!

    那正是说要消灭同临时常间满意下面多个标准化的靶子,该如何做呢?看上面:

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

    (译者:有未有很坑爹的认为到?所以,建议在遇见跨关系的多值查询时,尽量使用Q查询卡塔尔国

    使用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的时候,请小心了!卡塔尔

    活动转义百分符号和下划线

    在原生SQL语句中%标记有独特的功力。Django帮你活动的转义了百分符号和下划线,你能够和平日字符相符选用它们,如下所示:

    >>> Entry.objects.filter(headline__contains='%')
    # 它和下面的一样
    # SELECT ... WHERE headline LIKE '%%%';
    
    缓存和查询集结

    各种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对象。

    一对多(外键)

    正向查询
    一贯通过圆点加属性,访谈外键对象:

    >>> 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的办事章程与前面提到的“反向”大器晚成对多关系的用法同样。

    唯大器晚成的分歧在于属性的名号:定义ManyToMany菲尔德的模子使用该字段的性质名称,而“反向”模型使用源模型的小写名称加上'_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
    
    反向关联是什么促成的?

    有的ORM框架供给你在关系的两端都进展定义。Django的开荒者认为那违反了D途锐Y (Don’t Repeat Yourself)原则,所以在Django中您只要求在后生可畏端举行定义。

    那么那是怎么贯彻的吗?因为在关乎的模型类未有被加载此前,一个模型类根本不清楚有啥类和它事关。

    答案在app registry!在Django运行的时候,它会导入全体INSTALLED_应用程式S中的应用和每一个应用中的模型模块。每成立二个新的模龙时,Django会自动抬高反向的涉及到独具涉嫌的模子。借使涉嫌的模型还从未导入,Django将保存关联的记录并在关乎的模子导入时增多那些关乎。

    是因为这几个原因,将模型所在的运用都定义在INSTALLED_APPS的利用列表中就体现特别主要性。不然,反向关联将不能够科学专门的学业。

    经过关系对象进行查询

    论及关联对象的查询与符合规律值的字段查询遵循平等的规行矩步。当你钦定询问要求相称的值时,你能够行使一个指标实例可能指标的主键值。

    举个例子,要是您有一个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未有强制钦点你非要使用它的某部意义或模块。

    本文由澳门新葡萄京最大平台发布于动作小游戏,转载请注明出处:中文文档

    关键词:

上一篇:反晋联盟的形成

下一篇:没有了