模型.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多查詢語句