Вопрос
отсюда.
Есть три модели (диалог, сообщения и пользователи):
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>
Что лучше? Голосуем