Django中的外键向后导航

时间:2011-03-18 05:11:50

标签: django django-models foreign-keys

对于这个例子:

class Blog(models.Model):
    name = models.CharField(max_length=100)
    tagline = models.TextField()

    def __unicode__(self):
        return self.name

class Author(models.Model):
    name = models.CharField(max_length=50)
    email = models.EmailField()

    def __unicode__(self):
        return self.name

class Entry(models.Model):
    blog = models.ForeignKey(Blog, related_name='entries')
    headline = models.CharField(max_length=255)
    body_text = models.TextField()
    pub_date = models.DateTimeField()
    mod_date = models.DateTimeField()
    authors = models.ManyToManyField(Author)
    n_comments = models.IntegerField()
    n_pingbacks = models.IntegerField()
    rating = models.IntegerField()

    def __unicode__(self):
        return self.headline

那么,如何查找所有包含其条目的博客?

我想做这样的事情

q = Blog.objects.all().entries.filter(...)

但它给了我一个错误。那么Django只支持将后向导航属性仅用于一个对象而不是一组对象吗?

3 个答案:

答案 0 :(得分:4)

假设您要过滤所有博客的条目,并获取您需要的条目的博客:

Blog.objects.filter(entry__headline__icontains="cats").distinct()

此处有一个博客与多个条目的关系,但此查询有效,并为您提供了标题为猫的条目的博客。

答案 1 :(得分:0)

如果您想获得与每个Blog相关联的所有条目,您可以执行以下操作:

blogs = Blog.objects.all()
for blog in blogs:
    blog.cached_entries = blog.entry_set.all()

虽然这看起来很整洁,但会进行n + 1次查询 - 获取所有博客的1个查询以及获取与博客相关联的每个条目的n个查询。

可以在一个查询中执行此操作,但如果您想通过博客隔离条目,则必须完成更多工作。

blog_with_entries = []
entries = Entry.objects.order_by('blog')
previous_blog = None
acc_entries = [] # accumulate entries of one blog

for entry in entries:
    if previous_blog != entry.blog:
        if previous_blog is not None:
            blog_with_entries.append((previous_blog, acc_entries))
        acc_entries = []
        previous_blog = entry.blog
    acc_entries.append(entry)
blog_with_entries.append((previous_blog, acc_entries))

答案 2 :(得分:-1)