ORM模型裏鏈接數據庫經常使用方法和QuerySet API

模型.objects:python

這個對象是django.db.models.manager.Manager的對象,這個類是一個空殼類,他上面的全部方法都是從'QuerySet'這個類上面拷貝過來的。所以咱們只要學會了'QuerySet',這個‘objects’也就知道如何使用了。數據庫

'Manage'源碼解析:django

、、、python函數

class_name = 'BaseManagerFromQuerySet'


Class_dict = {
    '_queryset_class':QuerySet      
}


Class_dict.update(cls.get_queryset_methods(QuerySet))

#type動態的時候建立類fetch

#第一個參數是用來指定建立的類的名字。 建立的類名是:BaseManagerFromQuerySetspa

#第二個參數是用來指定這個類的父類。code

#第三個參數是用來指定這個類的一些屬性和方法對象

return type(class_name,(cls,),class_dict)blog

 

 

_get_query_methods:這個方法就是將Queryset中的一些方法拷貝出來排序

 

##filter/exclude.annotate:過濾/排除知足條件的/給模型添加新的字段。

 

##order_by:

#根據建立的時間正序排序
articles = Article.objects.order_by("create_time")
# 根據建立的時間倒序排序
articles = Article.objects.order_by("-create_time")
# 根據做者的名字進行排序
articles = Article.objects.order_by("author__name")
# 首先根據建立的時間進行排序,若是時間相同,則根據做者的名字進行排序
articles = Article.objects.order_by("create_time",'author__name')

必定要注意的是,多個‘order_by’,會把前面排序的規則給打亂,而使用後面的排序方式。如:

articles = Article.objects.order_by("create_time").order_by("author__name")

 

它會根據做者的名字進行排序,而不是使用文章的建立時間。

固然,也能夠在模型定義的在‘Meta’類中定義'ordering'來指定默認的排序方式。如

    class Meta:
        db_table = 'book_order'
        ordering = ['create_time','-price']

 

還能夠根據`annotate`定義的字段進行排序。好比要實現圖書的銷量進行排序,那麼示例代碼以下:

books = Book.objects.annotate(order_nums=Count("bookorder")).order_by("-order_nums")
    for book in books:
        print('%s/%s'%(book.name,book.order_nums))

 

values:

有時候咱們在表中查找數據的時候,並非想要把全部的字段都提取出來,
有可能只想要其中的幾個字段,這時候就可使用`values`來實現,須要什麼字段,就把這個字段的名字傳到這個方法中

books = Book.object.values('id',‘name)

`values`的返回值一樣也是一個`QuerySet`對象,可是裏面裝的再也不是模型,而是字典

若是咱們想要提取的使者模型上關聯的對象的屬性,也是能夠的,查找方法跟`filter`的用法是同樣的

books=Book.object.values('id','name','author__name')


以上會提取`author`的`name`字段,若是想要更改這個默認的名字那麼可使用關鍵字參數

books=Book.objects.values('id','name',author_name=F('author__name'))

 

自定義的名字,不能和模型上自己擁有的字段同樣,好比以上‘author_name’若是取名叫作'author'就會報錯,由於「Book‘表裏自己就擁有一個字段叫作’author‘

在’vialues‘中,也可使用聚合函數來造成一個新的字段,好比想要獲取每本書的銷量

books=Book.objects.values('id','name',order_nums=Count('bookorder'))

若是調用'values'方法的時候,沒有傳遞任何的參數,name會獲取這個模型上的全部字段以及對應的值造成的字典

books=Book.objects.values
#bookS值以下:
###{'id':1,'name':'三國演義','pages':987,'price':108,rating:3.9,'author_id':3,'publisher_id':1}

 

values_list

跟value是同樣的做用,只不過這個方法返回的是’QuerySet‘中,裝的不是字典而是元組

books = Book.objects.values_list('id','name')

##結果是:(1,’三國演義‘)

 若是給`values_list`只指定一個字段,那麼能夠指定`flat=True`這樣返回的結果就不在是一個元組,而是這個字段的值

books=Book.objects.values_list('name',flat=True)

###結果是 '三國演義'

flat只能用在只有一個字段的狀況下,不然會報錯

 

all方法

這個返回簡單的一個`QuerySet`對象,這個對象沒有通過任何修改(好比:過濾等)

 

## select_related

在查找某個表的數據的時候,能夠一次性把相關聯的其餘表的數據都提取出來,這樣能夠在之後訪問相關聯的數據的時候,不用再次查找數據庫,能夠節省一些開銷

books=Book.objects.select_related('author','publisher')
for book in books: print(book.author.name)d #由於在提取Book的時候,使用了select_related,那麼之後再訪問book_author的時候,不會再次向數據庫從新發起查詢了

 注意:


注意:這個方法只能用在外鍵關聯的對象上,對於那種多對多,或者一對多的狀況,不能使用它來實現,而應該使用`perfetch_related`來實現

 

prefetch_related:

這個方法相似於select_related方法,也是用在查詢語句的時候,提早將指定的數據查找出來,只不過這個方法是是用來解決多對多或者多對一的狀況,這個方法會產生兩個查詢語句,因此,若是在這個方法中查詢使用外鍵關聯的模型的時候,也會產生兩個查詢語句,所以若是查詢的是外鍵關聯的模型,建議使用`select_related`方法。在查詢多對多或者多對一的關聯的隊形的時候,在使用模型怎麼訪問這個多對多,就在這方法中傳遞什麼字符串,好比要獲取圖書上的全部訂單,代碼以下

books=Book.objects.prefetch_related('bookorder_set')

須要注意的是:在使用`prefetch_related`查找出來的`bookorder_set`建議不要在對它進行任何操做,好比`filter`,否則又會產生N多查詢語句

相關文章
相關標籤/搜索