电竞比分网-中国电竞赛事及体育赛事平台

分享

django orm總結(jié)

 月影曉風(fēng) 2016-09-09

目錄
1.1.1 生成查詢
1.1.2 創(chuàng)建對(duì)象
1.1.3 保存修改的對(duì)象
1.1.4 保存 ForeignKey 和 ManyToManyField 字段
1.1.5 檢索對(duì)象
1.1.6 檢索所有的對(duì)象
1.1.7 過(guò)濾檢索特定對(duì)象
1.1.8 鏈接過(guò)濾
1.1.9 過(guò)濾結(jié)果集是唯一
1.2.1 結(jié)果集是延遲的
1.2.2 其他的QuerySet方法
1.2.3 限制 QuerySets
1.2.4 字段查找
1.2.5 跨關(guān)系查詢
1.2.6 過(guò)濾器可參考模型字段
1.2.7 緩存查詢集
1.2.8 比較對(duì)象
1.2.9 刪除對(duì)象
1.3.1 一次修改多個(gè)對(duì)象
1.3.2 關(guān)系對(duì)象
1.3.3 One-to-many關(guān)系
1.3.4 Many-to-many關(guān)系
1.3.5 One-to-one關(guān)系


1.1.1 生成查詢
你創(chuàng)建完數(shù)據(jù)模型,django會(huì)自動(dòng)提供給你數(shù)據(jù)庫(kù)抽象的API,可以創(chuàng)建、獲取、修改、刪除對(duì)象,本篇文檔講解如何使用API。

我們參考下面模型,一個(gè)weblog:

復(fù)制代碼
#博客
class Blog(models.Model):
    name = models.CharField(max_length=100)
    tagline = models.TextField()

    def __unicode__(self):
        return self.name
#作者
class Author(models.Model):
    name = models.CharField(max_length=50)
    email = models.EmailField()

    def __unicode__(self):
        return self.name

#目錄
class Entry(models.Model):
    blog = models.ForeignKey(Blog)
    headline = models.CharField(max_length=255)
    body_text = models.TextField()
    pub_date = models.DateTimeField()
    authors = models.ManyToManyField(Author)
    n_comments = models.IntegerField()
    n_pingbacks = models.IntegerField()
    rating = models.IntegerField()

    def __unicode__(self):
        return self.headline
復(fù)制代碼

 

1.1.2 創(chuàng)建對(duì)象

用python對(duì)象描述數(shù)據(jù)庫(kù)表的數(shù)據(jù),django使用一個(gè)直觀的系統(tǒng),一個(gè)模型類描述一個(gè)數(shù)據(jù)表,一個(gè)類的實(shí)例描述表的一條詳細(xì)記錄。使用模型的save()方法將對(duì)象創(chuàng)建到數(shù)據(jù)庫(kù)。

from mysite.blog.models import Blog

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

只有執(zhí)行save方法時(shí),django才會(huì)執(zhí)行sql把對(duì)象寫(xiě)入數(shù)據(jù)庫(kù)。


1.1.3 保存修改的對(duì)象

保存修改仍然使用save()方法

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


1.1.4 保存 ForeignKey 和 ManyToManyField 字段

cheese_blog = Blog.objects.get(name="Cheddar Talk")
entry.blog = cheese_blog #為 ManyToManyField 增加記錄
entry.save()
joe = Author.objects.create(name="Joe") entry.authors.add(joe) #為 ForeignKey 增加記錄


1.1.5 檢索對(duì)象
從數(shù)據(jù)庫(kù)里檢索對(duì)象,可以通過(guò)模型的Manage來(lái)建立QuerySet,一個(gè)QuerySet表現(xiàn)為一個(gè)數(shù)據(jù)庫(kù)中對(duì)象的結(jié)合,他可以有0個(gè)一個(gè)或多個(gè)過(guò)濾條件,在SQL里QuerySet相當(dāng)于select語(yǔ)句用where或limit過(guò)濾。你通過(guò)模型的Manage來(lái)獲取QuerySet,每個(gè)模型至少有一個(gè)Manage


1.1.6 檢索所有的對(duì)象

檢索表中所有數(shù)據(jù),最簡(jiǎn)單的方式是用all().

all_entries = Entry.objects.all()


1.1.7 過(guò)濾檢索特定對(duì)象

檢索過(guò)濾特定查詢結(jié)果,有兩個(gè)方法。
filter(**kwargs) 返回一個(gè)新的匹配查詢參數(shù)后的QuerySet
exclude(**kwargs) 返回一個(gè)新的不匹配查詢參數(shù)后的QuerySet

Entry.objects.filter(pub_date__year=2006)


1.1.8 鏈接過(guò)濾

Entry.objects.filter(headline__startswith='What')
         .exclude(pub_date__gte=datetime.now())
         .filter(pub_date__gte=datetime(2005, 1, 1))


1.1.9 過(guò)濾結(jié)果集是唯一

每次你完成一個(gè)QuerySet,你獲得一個(gè)全新的結(jié)果集,不包括前面的。每次完成的結(jié)果集是可以貯存,使用或復(fù)用
q1 = Entry.objects.filter(headline__startswith="What")
q2 = q1.exclude(pub_date__gte=datetime.now())
q3 = q1.filter(pub_date__gte=datetime.now())

三個(gè)QuerySets是分開(kāi)的,第一個(gè)是headline以"What"單詞開(kāi)頭的結(jié)果集,第二個(gè)是第一個(gè)的子集,即pub_date不大于現(xiàn)在的,第三個(gè)是第一個(gè)的子集 ,pub_date大于現(xiàn)在的


1.2.1 結(jié)果集是延遲的

QuerySets是延遲的,創(chuàng)建QuerySets不會(huì)觸及到數(shù)據(jù)庫(kù)操作,你可以多個(gè)過(guò)濾合并到一起,直到求值的時(shí)候django才會(huì)開(kāi)始查詢。如:

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

雖然看起來(lái)執(zhí)行了三個(gè)過(guò)濾條件,實(shí)際上最后執(zhí)行print q的時(shí)候,django才開(kāi)始查詢執(zhí)行SQL到數(shù)據(jù)庫(kù)。


1.2.2 其他的QuerySet方法
大多數(shù)情況你使用all()、filter()和exclude()


1.2.3 限制 QuerySets

使用python的數(shù)組限制語(yǔ)法限定QuerySet,如:
取前5個(gè)

Entry.objects.all()[:5]

 

取第五個(gè)到第十個(gè)

Entry.objects.all()[5:10]

 

一般的,限制QuerySet返回新的QuerySet,不會(huì)立即求值查詢,除非你使用了"step"參數(shù)

Entry.objects.all()[:10:2]
Entry.objects.order_by('headline')[0]
Entry.objects.order_by('headline')[0:1].get()


1.2.4 字段查找

字段查找是指定SQL語(yǔ)句的WHERE條件從句,通過(guò)QuerySet的方法filter(), exclude()和get()指定查詢關(guān)鍵字。
基本查詢field__lookuptype=value
例如:

Entry.objects.filter(pub_date__lte='2006-01-01')

轉(zhuǎn)換為SQL:

SELECT * FROM blog_entry WHERE pub_date <= '2006-01-01';

如果你傳了無(wú)效的參數(shù)會(huì)拋異常

 

數(shù)據(jù)庫(kù)API 支持一些查詢類型,下面體驗(yàn)一下:
a、exact

Entry.objects.get(headline__exact="Man bites dog")

等價(jià)于

SELECT ... WHERE headline = 'Man bites dog';

如果查詢沒(méi)有提供雙下劃線,那么會(huì)默認(rèn) __exact=

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

b、iexact——忽略大小寫(xiě)

Blog.objects.get(name__iexact="beatles blog")

blog title會(huì)匹配 "Beatles Blog", "beatles blog", 甚至 "BeAtlES blOG".

c、contains——包含查詢,區(qū)分大小寫(xiě)

Entry.objects.get(headline__contains='Lennon')

轉(zhuǎn)化為SQL

SELECT ... WHERE headline LIKE '%Lennon%';

icontains 不區(qū)分大小寫(xiě)

startswith,endswith,istartswith,iendswith
前模糊匹配,后模糊匹配


1.2.5 跨關(guān)系查詢

Entry.objects.filter(blog__name__exact='Beatles Blog')

這個(gè)可以跨越你想要的深度。

反向跨關(guān)系查詢

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


如果跨越多層關(guān)系查詢,中間模型沒(méi)有值,django會(huì)作為空對(duì)待不會(huì)發(fā)生異常。

Blog.objects.filter(entry__author__name='Lennon');
Blog.objects.filter(entry__author__name__isnull=True);
Blog.objects.filter(
entry__author__isnull=False,
entry__author__name__isnull=True);


1.2.6 過(guò)濾器可參考模型字段

目前給的例子里,我們建立了過(guò)濾,比照模型字段值和一個(gè)固定的值,但是如果我們想比較同一個(gè)模型里的一個(gè)指端和另一個(gè)字段的值,django提供F()——專門(mén)取對(duì)象中某列值的操作

from django.db.models import F
Entry.objects.filter(n_pingbacks__lt=F('n_comments'))

注:n_pingbacks、n_comments為模型Entry屬性

django支持加減乘除和模計(jì)算

Entry.objects.filter(n_pingbacks__lt=F('n_comments') * 2) 
Entry.objects.filter(rating__lt=F('n_comments') + F('n_pingbacks')) 
Entry.objects.filter(author__name=F('blog__name'))

 

主鍵查詢捷徑

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

 

不僅限于__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) # Explicit form
Entry.objects.filter(blog__id=3) # __exact is implied
Entry.objects.filter(blog__pk=3) # __pk implies __id__exact

 

like語(yǔ)句轉(zhuǎn)義百分號(hào)

Entry.objects.filter(headline__contains='%')

轉(zhuǎn)義為

SELECT ... WHERE headline LIKE '%\%%';


1.2.7 緩存查詢集

每個(gè)QuerySet都包含一個(gè)緩存,以盡量減少對(duì)數(shù)據(jù)庫(kù)的訪問(wèn)。理解他的工作原理很重要,可以寫(xiě)出最高效的代碼。
在最新創(chuàng)建的QuerySet里,緩存是空的。在第一次QuerySet被取值,因此數(shù)據(jù)庫(kù)查詢發(fā)生,django把查詢結(jié)果放入緩存,并返回給請(qǐng)求,隨后的查詢?nèi)≈禃?huì)復(fù)用緩存中的結(jié)果。

保持緩存的思想習(xí)慣,因?yàn)槿绻悴徽_使用查詢緩存會(huì)有麻煩。例如下面例子會(huì)創(chuàng)建兩個(gè)QuerySet

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

這樣意味著數(shù)據(jù)庫(kù)查詢會(huì)執(zhí)行兩次,實(shí)際兩次數(shù)據(jù)庫(kù)加載

為了避免這個(gè)問(wèn)題,簡(jiǎn)單保存QuerySet復(fù)用

queryset = Poll.objects.all()
print [p.headline for p in queryset] # Evaluate the query set.
print [p.pub_date for p in queryset] # Re-use the cache from the evaluation.


1.2.8 比較對(duì)象

比較兩個(gè)模型實(shí)例,使用python標(biāo)準(zhǔn)的運(yùn)算符,兩個(gè)等號(hào)==

some_entry == other_entry
some_entry.id == other_entry.id
some_obj == other_obj
some_obj.name == other_obj.name


1.2.9 刪除對(duì)象

刪除方法是很方便的,方法名為delete(),這個(gè)方法直接刪除對(duì)象沒(méi)有返回值

e.delete()

你也可以批量刪除對(duì)象,每個(gè)QuerySet有一個(gè)delete()方法,能刪除 QuerySet里所有對(duì)象


1.3.1 一次修改多個(gè)對(duì)象

有時(shí)候你想給QuerySet里所有對(duì)象的一個(gè)字段賦予特定值,你可以使用 update()方法
例如:

# Update all the headlines with pub_date in 2007.
Entry.objects.filter(pub_date__year=2007).update(headline='Everything is the same')

 

這個(gè)方法只能用于無(wú)關(guān)聯(lián)字段和外鍵

b = Blog.objects.get(pk=1)
# Change every Entry so that it belongs to this Blog.
Entry.objects.all().update(blog=b)

 

update()方法不返回任何值,QuerySet不支持save方法,如果要執(zhí)行save,可以如下:

for item in my_queryset:
item.save()

 

update也可以使用F()

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

 

1.3.2 關(guān)系對(duì)象

當(dāng)你在model里定義一個(gè)關(guān)系時(shí),模型實(shí)例會(huì)有一個(gè)方便的API來(lái)訪問(wèn)關(guān)系對(duì)象。用本頁(yè)上面的模型舉個(gè)例子,一個(gè)Entry
對(duì)象可以得到blog對(duì)象,訪問(wèn)blog屬性e.blog。
django也創(chuàng)建API來(lái)訪問(wèn)關(guān)系對(duì)象的另一邊,一個(gè)blog對(duì)象訪問(wèn)Entry列表b.entry_set.all().


1.3.3 One-to-many關(guān)系

如果一個(gè)對(duì)象有ForeignKey,這個(gè)模型實(shí)例訪問(wèn)關(guān)系對(duì)象通過(guò)簡(jiǎn)單的屬性

e = Entry.objects.get(id=2)
e.blog # Returns the related Blog object.

你可以憑借外鍵屬性獲取和賦值,修改外鍵值知道執(zhí)行save()方法才會(huì)保存到數(shù)據(jù)庫(kù)

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

如果ForeignKey 設(shè)置了null=True 你可以賦值為None

復(fù)制代碼
e = Entry.objects.get(id=2)
print e.blog # Hits the database to retrieve the associated Blog.
print e.blog # 不會(huì)在向數(shù)據(jù)庫(kù)取; 使用緩存中的值.

e = Entry.objects.select_related().get(id=2)
print e.blog # 不會(huì)在向數(shù)據(jù)庫(kù)取; 使用緩存中的值.
print e.blog # 不會(huì)在向數(shù)據(jù)庫(kù)取; 使用緩存中的值.

b = Blog.objects.get(id=1)
b.entry_set.all() # 返回所有blog的關(guān)聯(lián)對(duì)象.

# b.entry_set is a Manager that returns QuerySets.
b.entry_set.filter(headline__contains='Lennon')
b.entry_set.count()


b = Blog.objects.get(id=1)
b.entries.all() # 返回所有blog的關(guān)聯(lián)對(duì)象

# b.entries is a Manager that returns QuerySets.
b.entries.filter(headline__contains='Lennon')
b.entries.count()
復(fù)制代碼

 

add(obj1, obj2, ...) 增加多個(gè)關(guān)系對(duì)象
create(**kwargs) 建立新對(duì)象
remove(obj1, obj2, ...) 去除多個(gè)關(guān)系對(duì)象
clear() 清理所有關(guān)系對(duì)象

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


1.3.4 Many-to-many關(guān)系

復(fù)制代碼
e = Entry.objects.get(id=3)
e.authors.all() # 返回Entry所有authors .
e.authors.count()
e.authors.filter(name__contains='John')

a = Author.objects.get(id=5)
a.entry_set.all() # 返回Author所有entry .
復(fù)制代碼


1.3.5 One-to-one關(guān)系

class EntryDetail(models.Model):
    entry = models.OneToOneField(Entry)
    details = models.TextField()

ed = EntryDetail.objects.get(id=2)
ed.entry # 返回 Entry 對(duì)象.

 

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買(mǎi)等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多