Groupby с использованием ORM Django для получения словаря списков между двумя моделями

У меня есть две модели, User и Gift:

class User(models.Model):
    name = models.CharField(max_length=150, null=True, blank=True)
    ...


class Gift(models.Model):
    user = models.ForeignKey(
        "User",
        related_name="users",
        on_delete=models.CASCADE,
    )
    ...

Теперь я хочу создать словарь списков, чтобы иметь список gifts для каждого user, так что я могу быстро найти ids подарков, которые есть у некоторых пользователей, в цикле for, без необходимости запрашивать базу данных много раз. Я придумал следующее:

from itertools import groupby
gifts_grouped = {
    key: [v.id for v in value] for key, value in groupby(gifts, key=lambda v: v.user_id)
}

Теперь каждый раз, когда я хочу просмотреть подарки пользователя, я могу просто сделать:

gifts_grouped[id_of_a_user]

И вернет список с идентификаторами подарков для этого пользователя. Сейчас это кажется Python-решением проблемы, которую можно легко решить с помощью Django. Но я не знаю как. Можно ли добиться таких же результатов с помощью ORM в Django?

Нет необходимости делать это, вы можете запросить с помощью:

users = User.objects.prefetch_related('users')

Для пользователя вы можете:

for user in users:
    for gift in user.users.all():
        print(user, ' -> ', gift)

Причина, по которой вы обращаетесь к ним через .users - это параметр related_name=.. [Django-doc], который также показывает, почему это не очень хорошее имя. Вы можете использовать:

from django.conf import settings


class User(models.Model):
    name = models.CharField(max_length=150, null=True, blank=True)
    # …


class Gift(models.Model):
    user = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        related_name='gifts',
        on_delete=models.CASCADE,
    )
    # …

Затем вы получаете доступ к ним с помощью:

users = User.objects.prefetch_related('gifts')
for user in users:
    for gift in user.gifts.all():
        print(user, ' -> ', gift)

Note: It is normally better to make use of the settings.AUTH_USER_MODEL [Django-doc] to refer to the user model, than to use the User model [Django-doc] directly. For more information you can see the referencing the User model section of the documentation.

Вернуться на верх