Django提供了很多基於類的通用視圖(Class Based View),可以幫我們簡化執行以下操作的代碼。這些基類視圖提供了:get_queryset,、get_context_data、get_object等方法。
展示對象列表(比如所有用戶,所有文章)- 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