1.5 與QuertSet和管理器協同工做

  前述內容設置了一個全功能管理站點,並可對博客內容進行處理.本節將討論如何從數據庫中獲取信息並與其進行交互.Django設置了強大的數據庫抽象API,並以此方便地建立、獲取、更新以及刪除對象.同時,Django中的對象關係映射器兼容於MySQL、PostgreSQL、SQLite、Oracle.須要注意的是,咱們可在項目的settings.py文件中的DATABASES設置項中定義當前項目的數據庫.Django可一次與多個數據庫協同工做,用戶能夠對數據庫路由器進行編程,以建立自定義路由方案.python

  

  在數據庫模型建立完畢後,Django提供了相應的API可與其進行交互.shell

 

1.5.1 建立對象數據庫

  打開終端並運行如下命令啓動Python shell:django

python manage.py shell

  隨後輸入下列代碼行編程

from django.contrib.auth.models import User
from blog.models import Post
user = User.objects.get(username='admin')
post = Post(title='Another post',slug='another-post',body='Post body',author=user)
post.save()

  

  下面對上述代碼的執行內容進行簡要分析.首先,咱們經過用戶名admin獲取user對象,以下所示:緩存

user = User.objects.get(username='admin')

  這裏,get()方法可從數據庫中獲取單一對象.注意,該方法指望獲得與查詢匹配的結果.若是數據庫未返回任何結果,該方法將會拋出DoesNotExist異常:若是數據庫返回多條結果,則會拋出MultipleObjectsReturned異常.這兩個異常均爲與執行查詢對應的、模型類的屬性.服務器

  隨後利用定製title、slug以及body建立Post實例,並將以前檢索到的用戶設置爲帖子的做者,以下所示:post

post = Post(title='Another post',slug='another-post',body='Post body',author=user)

 

 

  !!!注意:測試

    此類對象位於內存中,且未實現數據庫的持久化操做.spa

    最後,利用save()方法將Post對象保存至數據庫,以下所示:

post.save()

  上述操做在後臺執行了INSERT SQL語句.前述內容討論了在內存中建立對象,並於隨後將其持久化至數據庫中.除此以外,還可經過create()這一單一操做方式建立對象,並將其持久化至數據庫中,以下所示:

Post.objects.create(title='One more post',slug='one-more-post',body='Post body.',author=user)

 

1.5.2 更新對象

  下面修改帖子的標題,並再次保存對象,對應代碼以下所示:

post.title = 'New title'
post.save()

  此處,save()方法執行UPDATE SQL語句.

  !!!注意:

    當調用了save()方法後,對象的變化內容方能持久化至數據庫中.

 

1.5.3 獲取對象

  Django對象關係映射機制(ORM)基於Queryset.Queryset表示爲一個源自數據庫的對象集合,其中包含了多個過濾器以對結果進行限制.咱們瞭解到經過get()方法獲取數據庫中的單一對象,並利用Post.objects.get()訪問該方法.相應的,每一個Django模型至少包含一個管理器,且默認管理器稱做objects.經過模型管理器,用戶可獲得一個Queryset對象.當從某個表中獲取全部的對象時,僅需使用默認對象管理器上的all()方法便可,以下:

all_posts = Post.objects.all()

  上述代碼顯示了Queryset的建立方式,並返回數據庫中的所有對象.注意,該Queryset還沒有被執行.Django中的Queryset具備延遲性,僅在強制操做下方得以被執行,這種行爲使得Queryset更加高效.若是未將Queryset設置爲某個變量,而是直接將其寫入python shell中,Queryset的SQL語句將被執行--此處將其強制至輸出結果中,以下:

Post.objects.all()

  

  1.使用filter()方法

  當過濾Queryset時,可食用管理器的filter()方法.例如,可利用下列Queryset得到2019年中發佈的所有帖子:

Post.objects.filter(publisher__year=2019)

  除此以外,還可經過多個字段進行過濾.例如,可經過包含用戶名admin的做者獲取發佈於2019年的全部帖子,以下:

Post.objects.filter(publisher__year=2019,author__username='admin')

  這至關於構建連接多個過濾器的同一Queryset,以下:

Post.objects.filter(publish__year=2017).filter(author__username='admin')

 

  !!!注意:

    包含字段查找方法的查詢操做可採用兩個下劃線予以構建,如publish__year;但同一標記也可用於相關模型的訪問字段,如author__username.

 

  2.使用exclude()方法

  利用過濾器的exclude()方法,可從Queryset中排除特定的結果.例如,可獲取標題不包含test的、發佈於2019年的所有帖子,以下:

Post.objects.filter(publish__year=2019).exclude(title__startswith='test')

 

  3.使用order_by()方法

  利用管理器的order_by()方法,可經過不一樣的字段對結果進行排序.例如,可獲取以標題排序的所有對象,以下:

Post.objects.order_by('title')

  這裏,默認爲升序操做.固然還可經過負號前綴進行降序排序,以下:

Post.objects.order_by('-title')

 

 

  1.5.4 刪除對象

  若是但願刪除某個對象,可經過delete()方法在對象實例中執行這一操做,以下:

post = Post.objects.get(id=1)
post.delete()

  !!!注意:

    刪除對象也會刪除ForeignKey對象(on_delete設置爲CASCADE)的依賴關係.

 

  1.5.5 評估Queryset

  咱們能夠鏈接多個過濾器到一個Queryset上,在Queryset計算以前並不會訪問數據庫.Queryset僅在如下場合被計算.

  • 首次迭代時
  • 當對Queryset訪問時,如Post.objects.all()[:3]
  • 當對Queryset緩存時
  • 當在Queryset上調用repr()或len()時
  • 當在Queryset上顯示調用list()時
  • 當在某個語句中對Queryset進行測試時,如bool()、or、and或者if

 

  1.5.6 建立模型管理器

  如前所述,對象表示爲每一個模型的默認管理器(可檢索數據庫中的所有對象).然而,咱們還可針對模型定義定製管理器.下面將建立定製管理器並檢索包含published狀態的所有帖子.

  對此,存在兩種方式可向模型中添加管理器,即添加額外的管理器方法,或者修改初始管理器Queryset.其中,第一個方法提供了相應的Queryset API,如Post.objects.my_manager();而第二個方法則提供了Post.my_manager.all().該管理器可經過Post.published.all()檢索帖子.

  下面編輯models.py文件並添加定製管理器,以下:

class PublishedManager(models.Manager):
    def get_queryset(self):
        return super(PublishedManager,self).get_queryset().filer(status='published')

class Post(models.Model):
    # ...
    objects = models.Manager()  # 默認manager
    published = PublishedManager()  # 定製的manager
 

  管理器的get_queryset()方法返回將被執行的Queryset.咱們將覆寫該方法,以在最終的Queryset中包含自定義過濾器.以前曾定義了定製管理器,並將其添加值Post模型中,此處可對其加以使用並執行查詢.

  經過如下命令再次啓用開發服務器:

python manage.py shell

  此處可利用下列命令檢索全部發布的帖子,其對應的標題以test開始

Post.published.filter(title__startswith='test')

相關文章
相關標籤/搜索