从多态关系的一对多关系的查询集中获取相关模型

时间:2014-08-29 20:48:35

标签: django django-models

第1步:

假设我有两个一对多的相关模型,例如:

from django.db import models
class Author(models.Model):
    name = models.CharField(max_length=100)

class Book(models.Model):
    name    = models.CharField(max_length=300)
    author  = models.ForeignKey(Author)
    pubdate = models.DateField()

如何获取所有作者的列表及其上一本书的名称(或者更确切地说是书籍对象本身)?

  • 每篇文章没有一个查询
  • 有些作者可能尚未出版一本书,我仍然希望它们在列表中(无)
  • 为了便于携带,我想避免使用手动SQL
  • 不应加载所有内存中的图书

第2步:

我不确定这是解决方案的重大差异。

假设我现在拥有Book的BookBook子类(使用django-polymorphic),我想知道所有作者上一张PictureBook的picture_url(如果不是,也想知道是否为。)

from polymorphic import PolymorphicModel
class Book(PolymorphicModel):
    name    = models.CharField(max_length=300)
    author  = models.ForeignKey(Author)
    pubdate = models.DateField()

class PictureBook(Book):
    picture_url = models.CharField(max_length=200)

不幸的是,documentation about annotate中的示例仅显示直接的最小值/最大值。如果我从所有的PictureBook开始,那么我会想念那些没有PictureBook的作者。 This question与我有关系,但很老。我正在使用Django 1.7。

1 个答案:

答案 0 :(得分:1)

在您的第一个示例中,如果关系设置如下:

from django.db import models
class Author(models.Model):
    name = models.CharField(max_length=100)
    books = models.ManyToMany(Book)

    def latest_book(self):
        """ 
        This is only efficient / accurate if you've prefetched books 
        in the right order!
        """
        if self.books.exists():
            return self.books.all()[0]
        return None


class Book(models.Model):
    name = models.CharField(max_length=300)
    pubdate = models.DateField()

然后使用1.7中引入的Prefetch对象:

from django.db.models import Prefetch
authors = Author.objects.all().prefetch_related(
    Prefetch('books', queryset=Books.objects.order_by('-pubdate')

for author in authors:
    print author.latest_book()

2个数据库查询,但当然要知道您正在为每个作者加载每本书到内存中。也就是说,使用Prefetch对象的queryset arg,你可能会提高效率。

我让latest_book成为作者的成员以保持示例代码的轻量级,但实际上您可能希望在作者模型的定义之外使用它,因为在这个特定的实现之外它没有用,并且调用了正确的预取。

我不熟悉django-polymorphic包,但我打赌你可以使用这种方法,因为预取也支持通用关系。