Предварительная выборка отношения "один ко многим" django ORM

Сейчас я работаю над функцией API, которая возвращает список друзей пользователей, а также все ссылки на фотографии этих пользователей. (Хотя мне нужна только ссылка, отсортированная по орде)

Ниже представлены мои модели с внешними ключами.

class Personimage(models.Model):
    photo_uuid = models.CharField(db_column='photoUUID', max_length=100, blank=True,
                                 primary_key=True, default='')
    user_id = models.ForeignKey('Member', db_column='userID', on_delete=models.CASCADE, blank=True,
                               null=True)
    ord = models.IntegerField(db_column='ord', blank=True, null=True)
    reference = models.CharField(db_column='reference', max_length=200, blank=True, null=True)

class Member(AbstractBaseUser):
    user_id = models.CharField(db_column='userID')

class Friends(models.Model):
    id = models.IntegerField(db_column='id', primary_key=True, blank=False, null=False)
    puser = models.ForeignKey('Member', on_delete=models.CASCADE, db_column='puser')
    suser = models.ForeignKey('Member', on_delete=models.CASCADE, db_column='suser',
                              related_name='secondary_friend')

Пока я смог сделать это:

friends = Friend.objects.filter(puser=cur_user).prefetch_related('suser')

    for r in friends:
        photos = Personimage.objects.filter(user_id=r.suser)
        united.append({'user_id': r.suser.user_id,
                       'name': r.suser.name,
                       'photos': [photo.reference for photo in photos.filter(user_id=r.suser)]})

но, как вы можете изобразить, это невероятно медленно, так как он должен сделать вызов в таблицу Personimage для каждого пользователя в списке друзей. Я знаю, что есть способ сделать это, используя prefetch_related или некоторую комбинацию этого и что-то еще, но я не могу найти, как это сделать где-нибудь в Интернете или в моих экспериментах. Самым близким, что я получил, было вернуть только одну фотографию для каждого из участников в друзьях.

1 ответ

Замените модель Friends на поле ManyToMany "friends" в классе Member. Также я не думаю, что вам нужно поле user_id - у вас есть поле id по умолчанию, вам не нужен псевдоним для этого (Django сделает это за вас).

class Member(AbstractBaseUser):
  friends = models.ManyToManyField('self')

Затем, чтобы получить данные в нужной форме:

friends = Member.objects.get(pk=cur_user).friend.all().prefetch_related('personimage_set')
united = []
for friend in friends:
  united.append({'user_id': friend.id, 
                 'name': friend.name, 
                 'photos': list(friend.personimage_set.values_list('reference', flat=True))})
Другие вопросы по тегам