Автор Тема: Доступ к связанной таблице без доп. запроса  (Прочитано 996 раз)

DigitalMag

  • Юный джедай
  • **
  • Сообщений: 89
  • Репутация +6/-0
    • Просмотр профиля
Вопрос отсюда.

Есть три модели (диалог, сообщения и пользователи):

class Dialog(models.Model):

    Partakers = models.ManyToManyField(Profile, related_name='dialogs', through="Dialog_Partakers")


class Messages(models.Model):
    Sender = models.ForeignKey(Profile)
    Time = models.DateTimeField(default=present_time)                           
    Content = models.TextField()
    Target = models.ForeignKey(Dialog, related_name='messages', related_query_name="messages")

Profile - обычная расширенная модель джанговского пользователя.

И мне нужно через Диалоги получить содержимое сообщения и имя его отправителя. С получением тела сообщения проблем уже не возникает: решил через subquery. Но вот с его отправителем проблема:

lastMessageSender = Subquery(Message.objects.filter(Target=OuterRef('id')).order_by('-id').values('Sender')[:1])
qs = qs.annotate(Sender=lastMessageSender).annotate(sender_name=lastMessageSender__username)

Пробовал так же через prefetch_related:

qs = qs.prefetch_related(Prefetch('messages', queryset=Message.objects.select_related('Target')))
И в шаблоне:

{{ dialog.messages.last.username }}
Ошибок не возникает, но в django toolbar вижу 4 лишних запроса.

Так вот, вопрос я решил через два варианта:

Вариант 1:

        MessageSender = Subquery(Profile.objects.filter(msgs=OuterRef('id')).order_by('-id').values('Image')[:1])
        qs = qs.prefetch_related(Prefetch('messages', queryset=Message.objects.annotate(sender_img=MessageSender).select_related('Target'), to_attr='mss'))
В шаблоне:
{% with dialog.mss|last as msg %}{{msg.sender_img}}{% endwith %}
Создается один лишний запрос

И вариант 2:

        #получаем картинку
        MessageSender = Subquery(Profile.objects.filter(msgs=OuterRef('id')).order_by('-id').values('Image')[:1])
        lastMessageSender = Subquery(Message.objects.filter(Target=OuterRef('id')).annotate(the_sender=MessageSender).order_by('-id').values('the_sender')[:1])
        qs = qs.annotate(SenderImg=lastMessageSender)

И в шаблоне:

<img src="{{ MEDIA_URL }}{{dialog.SenderImg }}" height=30 width=50>
Что лучше? Голосуем