Какой лучший способ Django сделать запрос, который охватывает несколько таблиц? - PullRequest
2 голосов
/ 24 марта 2010

У меня есть веб-приложение обзоров / оценок, а-ля Digg. Мое приложение django content имеет следующую модель:

class Content(models.Model):
    title = models.CharField(max_length=128)
    url = models.URLField(max_length=2048)
    description = models.TextField(blank=True)

class Recommendation(models.Model):
    user = models.ForeignKey(User)
    content = models.ForeignKey(Content)
    review = models.TextField()
    rating = models.PositiveSmallIntegerField()
    class Meta:
        unique_together = ('user', 'content')

class Subscription(models.Model):
    subscriber = models.ForeignKey(User, related_name='subscription_set')
    publisher = models.ForeignKey(User, related_name='publication_set')
    class Meta:
        unique_together = ('subscriber', 'publisher')

Я хочу создать страницу со всеми рекомендациями всех пользователей, на которых подписывается текущий пользователь (request.user).

Если я напишу это в SQL, я думаю, что в итоге получу запрос, подобный следующему:

select content_content.*, content_recommendation.*, auth_user.*
from content_content, content_recommendation, content_subscription, auth_user
where content_content.id = content_recommendation.content_id
 and content_recommendation.user_id = content_subscription.publisher_id 
 and content_subscription.subscriber_id = ?
 and auth_user.id = content_subscription.publisher_id;

Как бы я выразил это, используя API запросов Django? Я прочитал документы, но просто не могу разобраться с этим.

Ответы [ 2 ]

10 голосов
/ 24 марта 2010

Я бы использовал:

Recommendation.objects.filter(user__publication_set__subscriber=request.user).select_related()

При этом вы получите все объекты Рекомендации в соответствии с вашим запросом, а метод select_related загрузит все связанные объекты «Пользователь» и «Содержимое» в память, чтобы при последующем доступе к ним они не попали в БД.

То, как вы построите этот запрос, действительно имеет непосредственное отношение к вашей обработке возвращенных данных впоследствии. Может быть более или менее эффективно идти одним путем против другого, основываясь на том, что вы делаете с ним. alt text http://sonicloft.net/im/52

1 голос
/ 24 марта 2010

Я думаю, что это:

  Content.objects.filter(recommendation_set__user__publication_set__subscriber__pk=request.user.pk)/.distinct()/

или

  Recommendation.objects.filter(user__publication_set__subscriber__pk=request.user.pk)/.distinct()/

- в зависимости от того, какую модель вы хотите приобрести. Distinct () может понадобиться, чтобы избежать дублирования.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...