django orm總結,djangoorm

來源:互聯網
上載者:User

django orm總結,djangoorm

目錄
1.1.1 產生查詢
1.1.2 建立對象
1.1.3 儲存修改的對象
1.1.4 儲存 ForeignKey 和 ManyToManyField 欄位
1.1.5 檢索對象
1.1.6 檢索所有的對象
1.1.7 過濾檢索特定對象
1.1.8 連結過濾
1.1.9 過濾結果集是唯一
1.2.1 結果集是延遲的
1.2.2 其他的QuerySet方法
1.2.3 限制 QuerySets
1.2.4 欄位尋找
1.2.5 跨關係查詢
1.2.6 過濾器可參考模型欄位
1.2.7 緩衝查詢集
1.2.8 比較對象
1.2.9 刪除對象
1.3.1 一次修改多個對象
1.3.2 關聯性物件
1.3.3 One-to-many關係
1.3.4 Many-to-many關係
1.3.5 One-to-one關係


1.1.1 產生查詢
你建立完資料模型,django會自動提供給你資料庫抽象的API,可以建立、擷取、修改、刪除對象,本篇文檔講解如何使用API。

我們參考下面模型,一個weblog:

#部落格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

 

1.1.2 建立對象

用python對象描述資料庫表的資料,django使用一個直觀的系統,一個模型類描述一個資料表,一個類的執行個體描述表的一條詳細記錄。使用模型的save()方法將對象建立到資料庫。

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

只有執行save方法時,django才會執行sql把對象寫入資料庫。


1.1.3 儲存修改的對象

儲存修改仍然使用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 檢索對象
從資料庫裡檢索對象,可以通過模型的Manage來建立QuerySet,一個QuerySet表現為一個資料庫中對象的結合,他可以有0個一個或多個過濾條件,在SQL裡QuerySet相當於select語句用where或limit過濾。你通過模型的Manage來擷取QuerySet,每個模型至少有一個Manage


1.1.6 檢索所有的對象

檢索表中所有資料,最簡單的方式是用all().

all_entries = Entry.objects.all()


1.1.7 過濾檢索特定對象

檢索過濾特定查詢結果,有兩個方法。
filter(**kwargs) 返回一個新的匹配查詢參數後的QuerySet
exclude(**kwargs) 返回一個新的不匹配查詢參數後的QuerySet

Entry.objects.filter(pub_date__year=2006)


1.1.8 連結過濾

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


1.1.9 過濾結果集是唯一

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

三個QuerySets是分開的,第一個是headline以"What"單詞開頭的結果集,第二個是第一個的子集,即pub_date不大於現在的,第三個是第一個的子集 ,pub_date大於現在的


1.2.1 結果集是延遲的

QuerySets是延遲的,建立QuerySets不會觸及到資料庫操作,你可以多個過濾合并到一起,直到求值的時候django才會開始查詢。如:

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

雖然看起來執行了三個過濾條件,實際上最後執行print q的時候,django才開始查詢執行SQL到資料庫。


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


1.2.3 限制 QuerySets

使用python的數組限制文法限定QuerySet,如:
取前5個

Entry.objects.all()[:5]

 

取第五個到第十個

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

 

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

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


1.2.4 欄位尋找

欄位尋找是指定SQL語句的WHERE條件從句,通過QuerySet的方法filter(), exclude()和get()指定查詢關鍵字。
基本查詢field__lookuptype=value
例如:

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

轉換為SQL:

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

如果你傳了無效的參數會拋異常

 

資料庫API 支援一些查詢類型,下面體驗一下:
a、exact

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

等價於

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

如果查詢沒有提供雙底線,那麼會預設 __exact=

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

b、iexact——忽略大小寫

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

blog title會匹配 "Beatles Blog", "beatles blog", 甚至 "BeAtlES blOG".

c、contains——包含查詢,區分大小寫

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

轉化為SQL

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

icontains 不區分大小寫

startswith,endswith,istartswith,iendswith
前模糊比對,後模糊比對


1.2.5 跨關係查詢

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

這個可以跨越你想要的深度。

反向跨關係查詢

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


如果跨越多層關係查詢,中間模型沒有值,django會作為空白對待不會發生異常。

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 過濾器可參考模型欄位

目前給的例子裡,我們建立了過濾,比照模型欄位值和一個固定的值,但是如果我們想比較同一個模型裡的一個指端和另一個欄位的值,django提供F()——專門取對象中某列值的操作

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

註:n_pingbacks、n_comments為模型Entry屬性

django支援加減乘除和模計算

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 formBlog.objects.get(id=14) # __exact is impliedBlog.objects.get(pk=14) # pk implies id__exact

 

不僅限於__exact 查詢

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

 

跨越查詢

Entry.objects.filter(blog__id__exact=3) # Explicit formEntry.objects.filter(blog__id=3) # __exact is impliedEntry.objects.filter(blog__pk=3) # __pk implies __id__exact

 

like語句轉義百分比符號

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

轉義為

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


1.2.7 緩衝查詢集

每個QuerySet都包含一個緩衝,以盡量減少對資料庫的訪問。理解他的工作原理很重要,可以寫出最高效的代碼。
在最新建立的QuerySet裡,緩衝是空的。在第一次QuerySet被取值,因此資料庫查詢發生,django把查詢結果放入緩衝,並返回給請求,隨後的查詢取值會複用緩衝中的結果。

保持緩衝的思想習慣,因為如果你不正確使用查詢快取會有麻煩。例如下面例子會建立兩個QuerySet

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

這樣意味著資料庫查詢會執行兩次,實際兩次資料庫載入

為了避免這個問題,簡單儲存QuerySet複用

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 比較對象

比較兩個模型執行個體,使用python標準的運算子,兩個等號==

some_entry == other_entrysome_entry.id == other_entry.idsome_obj == other_objsome_obj.name == other_obj.name


1.2.9 刪除對象

刪除方法是很方便的,方法名為delete(),這個方法直接刪除對象沒有傳回值

e.delete()

你也可以大量刪除對象,每個QuerySet有一個delete()方法,能刪除 QuerySet裡所有對象


1.3.1 一次修改多個對象

有時候你想給QuerySet裡所有對象的一個欄位賦予特定值,你可以使用 update()方法
例如:

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

 

這個方法只能用於無關聯欄位和外鍵

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方法,如果要執行save,可以如下:

for item in my_queryset:item.save()

 

update也可以使用F()

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

 

1.3.2 關聯性物件

當你在model裡定義一個關係時,模型執行個體會有一個方便的API來訪問關聯性物件。用本頁上面的模型舉個例子,一個Entry
對象可以得到blog對象,訪問blog屬性e.blog。
django也建立API來訪問關聯性物件的另一邊,一個blog對象訪問Entry列表b.entry_set.all().


1.3.3 One-to-many關係

如果一個對象有ForeignKey,這個模型執行個體訪問關聯性物件通過簡單的屬性

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

你可以憑藉外鍵屬性擷取和賦值,修改外索引值知道執行save()方法才會儲存到資料庫

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

如果ForeignKey 設定了null=True 你可以賦值為None

e = Entry.objects.get(id=2)print e.blog # Hits the database to retrieve the associated Blog.print e.blog # 不會在向資料庫取; 使用緩衝中的值.e = Entry.objects.select_related().get(id=2)print e.blog # 不會在向資料庫取; 使用緩衝中的值.print e.blog # 不會在向資料庫取; 使用緩衝中的值.b = Blog.objects.get(id=1)b.entry_set.all() # 返回所有blog的關聯對象.# 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的關聯對象# b.entries is a Manager that returns QuerySets.b.entries.filter(headline__contains='Lennon')b.entries.count()

add(obj1, obj2, ...) 增加多個關聯性物件
create(**kwargs) 建立新對象
remove(obj1, obj2, ...) 去除多個關聯性物件
clear() 清理所有關聯性物件

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


1.3.4 Many-to-many關係

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 .

1.3.5 One-to-one關係

class EntryDetail(models.Model):    entry = models.OneToOneField(Entry)    details = models.TextField()ed = EntryDetail.objects.get(id=2)ed.entry # 返回 Entry 對象.

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.