Внешний ключ обратной навигации в Джанго - PullRequest
1 голос
/ 18 марта 2011

Для этого примера:

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 ]

4 голосов
/ 18 марта 2011

Допустим, вы хотите отфильтровать записи всех блогов и получить блоги, в которых есть записи, которые вам необходимы:

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

Здесь есть один блог со многими записями, но этот запрос работает и дает вам блоги, в которых есть записи с кошками в заголовках.

0 голосов
/ 18 марта 2011

Если вы хотите получить все записи, связанные с каждым 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))
0 голосов
/ 18 марта 2011
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...