1. 程式人生 > >Django get_object ,get_queryset方法

Django get_object ,get_queryset方法

改密 model pub LEDE port tar 時間 query mod

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

  • 展示對象列表(比如所有用戶,所有文章)- ListView

  • 展示某個對象的詳細信息(比如用戶資料,比如文章詳情) - DetailView

  • 通過表單創建某個對象(比如創建用戶,新建文章)- CreateView

  • 通過表單更新某個對象信息(比如修改密碼,修改文字內容)- UpdateView

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

  • 刪除某個對象 - DeleteView

get_queryset()方法

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

  1. # Create your views here.
  2. from django.views.generic import ListView
  3. from .models import Article
  4. class IndexView(ListView):
  5. model = Article

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

  1. # Create your views here.
  2. from django.views.generic import ListView
  3. from .models import Article
  4. from django.utils import timezone
  5. class IndexView(ListView):
  6. template_name = ‘blog/article_list.html‘
  7. context_object_name = ‘latest_articles‘
  8. def get_queryset(self):
  9. return Article.objects.filter(author = self.request.user).order_by(‘-pub_date‘)

上述代碼等同於:

  1. # Create your views here.
  2. from django.views.generic import ListView
  3. from .models import Article
  4. from django.utils import timezone
  5. class IndexView(ListView):
  6. model = Article
  7. template_name = ‘blog/article_list.html‘
  8. context_object_name = ‘latest_articles‘
  9. def get_queryset(self):
  10. qs = super().get_queryset() # 調用父類方法
  11. 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方法(如下圖所示)。因為調用了父類的方法,

  1. # Create your views here.
  2. from django.views.generic import ListView
  3. from .models import Article
  4. from django.utils import timezone
  5. class IndexView(ListView):
  6. queryset = Article.objects.all().order_by("-pub_date")
  7. template_name = ‘blog/article_list.html‘
  8. context_object_name = ‘latest_articles‘
  9. def get_context_data(self, **kwargs):
  10. context = super().get_context_data(**kwargs)
  11. context[‘now‘] = timezone.now() #只有這行代碼有用
  12. return context

get_object()方法

DetailView和EditView都是從URL根據pk或其它參數調取一個對象來進行後續操作。下面代碼通過DetailView展示一篇文章的詳細信息。

  1. # Create your views here.
  2. from django.views.generic import DetailView
  3. from django.http import Http404
  4. from .models import Article
  5. from django.utils import timezone
  6. class ArticleDetailView(DetailView):
  7. queryset = Article.objects.all().order_by("-pub_date") #等同於model = Article
  8. template_name = ‘blog/article_detail.html‘
  9. context_object_name = ‘article‘

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

  1. from django.views.generic import DetailView
  2. from django.http import Http404
  3. from .models import Article
  4. from django.utils import timezone
  5. class ArticleDetailView(DetailView):
  6. queryset = Article.objects.all().order_by("-pub_date")
  7. template_name = ‘blog/article_detail.html‘
  8. context_object_name = ‘article‘
  9. def get_object(self, queryset=None):
  10. obj = super().get_object(queryset=queryset)
  11. if obj.author != self.request.user:
  12. raise Http404()
  13. return obj

Django get_object ,get_queryset方法