1. 程式人生 > >如何使用Django通用檢視的get_queryset, get_context_data和get_object等方法

如何使用Django通用檢視的get_queryset, get_context_data和get_object等方法

Django提供了很多通用的基於類的檢視(Class Based View),可以幫我們簡化執行以下操作的程式碼。這些基於類的檢視還提供了get_querysetget_context_dataget_object等方法以便我們更靈活地使用它們。我們今天就來看下我們何時需要使用這些方法以及如何使用。本文出自【Django基礎知識(3): 檢視View的編寫及如何使用通用檢視

  • 展示物件列表(比如所有使用者,所有文章)- ListView

  • 展示某個物件的詳細資訊(比如使用者資料,比如文章詳情) - DetailView

  • 通過表單建立某個物件(比如建立使用者,新建文章)- 

    CreateView

  • 通過表單更新某個物件資訊(比如修改密碼,修改文字內容)- UpdateView

  • 使用者填寫表單後轉到某個完成頁面 - FormView

  • 刪除某個物件 - DeleteView

get_queryset()方法

正如其名,該方法可以返回一個量身定製的物件列表。當我們使用Django自帶的ListView展示所有物件列表時,ListView預設會返回Model.objects.all()。

# Create your views here.
from django.views.generic import ListView
from .models import Article

class IndexView(ListView):

    model = Article

然而這可能不是我們所需要的。當我們希望只展示作者自己發表的文章列表且按文章釋出時間逆序排列時,我們就可以通過更具體的get_queryset方法來返回一個我們想要顯示的物件列表。

# Create your views here.
from django.views.generic import ListView
from .models import Article
from django.utils import timezone

class IndexView(ListView):

    template_name = 'blog/article_list.html'
    context_object_name = 'latest_articles'

    def get_queryset(self):
        return Article.objects.filter(author = self.request.user).order_by('-pub_date')

上述程式碼等同於:

# Create your views here.
from django.views.generic import ListView
from .models import Article
from django.utils import timezone

class IndexView(ListView):

    model = Article
    template_name = 'blog/article_list.html'
    context_object_name = 'latest_articles'

    def get_queryset(self):
        qs = super().get_queryset() # 呼叫父類方法
        return qs.filter(author = self.request.user).order_by('-pub_date')

我們也可以在DetailView和EditView中定義get_queryset(),一旦定義了該方法那麼DetailView返回的一個具體物件只會從queryset裡查詢。

get_context_data()

get_context_data可以用於給模板傳遞模型以外的內容或引數,非常有用。例如現在的時間並不屬於Article模型。如果你想把現在的時間傳遞給模板,你還可以通過重寫get_context_data方法(如下圖所示)。因為呼叫了父類的方法,

# Create your views here.
from django.views.generic import ListView
from .models import Article
from django.utils import timezone

class IndexView(ListView):

    queryset = Article.objects.all().order_by("-pub_date")
    template_name = 'blog/article_list.html'
    context_object_name = 'latest_articles'

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['now'] = timezone.now() #只有這行程式碼有用
        return context
        

get_object()方法

DetailView和EditView都是從URL根據pk或其它引數調取一個物件來進行後續操作。下面程式碼通過DetailView展示一篇文章的詳細資訊。

# Create your views here.
from django.views.generic import DetailView
from django.http import Http404
from .models import Article
from django.utils import timezone

class ArticleDetailView(DetailView):

    queryset = Article.objects.all().order_by("-pub_date") #等同於model = Article
    template_name = 'blog/article_detail.html'
    context_object_name = 'article'

然而上述程式碼可能滿足不了你的需求。比如你希望一個使用者只能檢視或編輯自己發表的文章物件。當用戶檢視別人的物件時,返回http 404錯誤。這時候你可以通過更具體的get_object()方法來返回一個更具體的物件。程式碼如下:

from django.views.generic import DetailView
from django.http import Http404
from .models import Article
from django.utils import timezone

class ArticleDetailView(DetailView):

    queryset = Article.objects.all().order_by("-pub_date")
    template_name = 'blog/article_detail.html'
    context_object_name = 'article'

    def get_object(self, queryset=None):
        obj = super().get_object(queryset=queryset)
        if obj.author != self.request.user:
            raise Http404()
        return obj