объединение запросов в Django - PullRequest
0 голосов
/ 27 октября 2009

У меня есть запрос, который возвращает мне 32 аватара из моего приложения для аватаров:

newUserAv = Avatar.objects.filter(valid=True)[:32]

Я хотел бы объединить это с запросом к пользовательской модели Django Auth, чтобы я мог получить последние 32 человека, у которых есть изображения аватара, отсортированные по дате присоединения.

Как лучше всего связать этих двоих вместе?

Приложение аватара было приложением многократного использования, и его модель:

image = models.ImageField(upload_to="avatars/%Y/%b/%d", storage=storage)
user = models.ForeignKey(User)
date = models.DateTimeField(auto_now_add=True)
valid = models.BooleanField()

Обратите внимание, что поле даты, это дата обновления аватара, поэтому не подходит для моей цели

Ответы [ 2 ]

2 голосов
/ 27 октября 2009

Либо вы помещаете поле в свой собственный класс пользователя (вам может потребоваться создать подкласс пользователя или создать с django.contrib.auth.models.User), которое указывает, что у пользователя есть аватар. Чем вы можете легко сделать запрос.

Или сделать что-то подобное:

from django.utils.itercompat import groupby
avatars = Avatar.objects.select_related("user").filter(valid=True).order_by("-user__date_joined")[:32]
grouped_users = groupby(avatars, lambda x: x.user)
user_list = []
for user, avatar_list in grouped_users:
    user.avatar = list(avatar_list)[0]
    user_list.append(user)
# user_list is now what you asked for in the first_place: 
# a list of users with their avatars

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

Объяснение фрагмента кода: Аватары большинства из 32 недавно присоединившихся пользователей запрашиваются вместе со связанным пользователем, поэтому нет необходимости запрашивать базу данных ни для одного из них в следующем коде. Список аватаров затем группируется с пользователем в качестве ключа. list получает все элементы от генератора avatar_list, а первый элемент (должен быть только один) назначается user.avatar

Обратите внимание, что в этом нет необходимости, вы всегда можете сделать что-то вроде:

for avatar in avatars:
    user = avatar.user

Но может быть более естественным получить доступ к аватарам пользователя user.avatar.

0 голосов
/ 27 октября 2009

Невозможно объединить запросы на двух разных базовых моделях. Django не позволит вам сделать это (он выдаст ошибку, сообщающую вам именно это).

Однако, если у вас есть чужой ключ от одной модели к другой, то добавление select_related () к вашему запросу приведет к загрузке связанных объектов в память в одном запросе к БД, чтобы вы могли получить к ним доступ, не возвращаясь в БД.

...