如何在django中创建具有较少查询的视图

时间:2013-12-02 07:45:54

标签: python django django-views django-queryset

Models.py

class Book(models.Model):
  created_at = models.DateTimeField(auto_now_add=True, editable=False)
  name = models.CharField(max_length=255, unique=True)
  slug = models.SlugField(max_length=255, blank=True, default='', unique=True)

class BookTranslation(models.Model):
  book = models.ForeignKey(Book, related_name='book_translations')
  language = models.CharField(max_length=2, choices=LANGUAGE_CHOICES)

class Chapter(models.Model):
  chapter = models.IntegerField()
  book_translation = models.ForeignKey(BookTranslation, related_name='related_chapters')

class Page(models.Model):
  chapter = models.ForeignKey(Chapter, related_name='related_pages')
  page = models.IntegerField()
  url = models.CharField(max_length=255)

urls.py

url(r'^(?P<language>[\w-]{2})-book/(?P<slug>[\w-]+)/(?P<chapter>\d+)/(?P<page>\d+)/$",
  PageView(), 
  name="page")

我尝试了不同的方法来制作PageView()并最终得到了这个:

class PageView(DetailView):
  model = Book
  template_name = 'bookinfo/book_page.html'
  context_object_name = 'book'

  def get_context_data(self, **kwargs):
    context = super(PageView, self).get_context_data(**kwargs)

    context['book_translation'] = BookTranslation.objects.get(
        book=context['book'], language=self.kwargs['language'])

    context['chapter'] = Chapter.objects.get(
        book_translation=context['book_translation'].id, chapter=self.kwargs['chapter'])

    context['page'] = Page.objects.get(
        chapter=context['chapter'].id, page=self.kwargs['page'])

    context['chapter_list'] = Chapter.objects.filter(
        book_translation=context['book_translation'].id)

    context['page_list'] = Page.objects.filter(
        chapter=context['chapter'].id)
    return context

但是这样,每当我打开这个页面时,我向DB发出6个请求,当我可以轻松地在上下文['book'],context ['book_translation'] context ['chapter']中获取参数时context ['page']带有像这样的单一SQL查询:

SELECT *
FROM Book b, BookTranslation bt, Chapter c, Page p
WHERE b.slug=self.kwargs['slug'] and 
  b.name=bt.book_id and
  bt.language=self.kwargs['language'] and 
  c.book_translation_id=bt.id and
  c.chapter=self.kwargs['chapter'] and 
  c.id=p.chapter_id and 
  p.page=self.kwargs['page']

有人可以解释一下我如何才能使这个View(最好是基于类)的性能更高?我可能不明白它们是如何工作的......

1 个答案:

答案 0 :(得分:0)

如果要检索相关的外键,请使用select_related覆盖get_queryset SingleObjectMixin,如下所示:

class PageView(DetailView):

    ...

    def get_queryset(self, *args, **kwargs):
        qs = super(PageView, self).get_queryset(*args, **kwargs)
        return qs.select_related()

这将获取单个查询中的所有相关对象,因此只要不评估查询集,就不应再次查询视图get_context_data中的所有相关对象。

参考:https://docs.djangoproject.com/en/1.6/ref/models/querysets/#select-related