代码之家  ›  专栏  ›  技术社区  ›  Zulan

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

  •  0
  • Zulan  · 技术社区  · 12 年前

    步骤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步:

    我不确定这在解决方案中是否有显著差异。

    假设现在我有本书的I PictureBook子类(使用django多态),我想知道所有作者上一本PictureBook的picture_url(如果没有,也可以是None)。

    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 仅显示直接最小/最大值。如果我从所有绘本开始,那么我会怀念那些没有绘本的作者。 This question 是什么相关的,但很古老。我使用的是Django 1.7。

    1 回复  |  直到 9 年前
        1
  •  1
  •   Casey Kinsey    12 年前

    在第一个示例中,如果关系设置为:

    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()
    

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

    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 Author的成员,以保持示例代码的简洁,但实际上,您可能希望这超出Author模型的定义,因为它在调用适当预取的特定实现之外没有用处。

    我不熟悉django多态包,但我打赌您可以使用这种方法来获得优势,因为预取也支持通用关系。

    推荐文章