Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Adding a property to a queryset in Django

Tags:

python

django

I'm creating a messaging system and part of what I want to do is based on whether the user is a sender or a receiver of a message, different CSS loads. I'm trying to achieve this by attaching a property to each message object that identifies this.

I have my message

#models.py
class Message(models.Model):
    def __unicode__(self):
        return unicode(self.time_date)

    message_from = models.ForeignKey(User, related_name="%(class)s_message_from")
    message_to = models.ForeignKey(User, related_name="%(class)s_message_to")
    message = models.TextField()
    file = models.FileField(blank=True, null=True)
    read = models.BooleanField(default=False)
    time_date = models.DateTimeField(default=django.utils.timezone.now)
    job = models.ForeignKey(Job, blank=True, null=True)

and my view to get the messages:

def view_messages(request):
    messages = Message.objects.filter(message_to=request.user, job_id=None).distinct('message_from')
    messages_from_user_ids = messages.values_list('message_from', flat=True).distinct()

    messages_from_user = User.objects.filter(id__in=messages_from_user_ids)

    messages = Message.objects.filter(
        Q(message_to=request.user) & Q(message_from_id=messages_from_user_ids[0]) & Q(job_id=None) | Q(
            message_from_id=messages_from_user_ids[0]) & Q(
            message_from_id=request.user) & Q(job_id=None)).order_by('time_date')

    messages = Message.objects.annotate(foo='true') # error

    return render(request, 'freelancestudent/general/messages.html', {'messages': messages,
                                                                      'messages_from': messages_from_user})

What I was trying to achieve in the line commented error was to simply test annotations by annotating the string 'true' to every message object, accessible under foo. This gives me the error 'str' object has no attribute 'resolve_expression'.

What I'm ultimately trying to achieve, in case I'm going about this the wrong way, is to check if the user is the sender. The idea i had of achieving it was to do something like this:

for message in messages:
    if message_from == request.user.id:
        messages.annotate(sender=True)

Though, this isn't the right syntax. I'm not sure annotate is the right function, either. Any ideas?

like image 526
Nanor Avatar asked Feb 08 '23 21:02

Nanor


1 Answers

If you are looping through the queryset, don't try to use annotate, just set an attribute on the instance.

for message in messages:
    if message_from == request.user.id:
        message.sender = True

Alternatively, I think you could use annotate with Case:

from django.db.models import BooleanField, Case, Value, When

messages = Message.annotate(
    sender=Case(
        When(message_from=request.user, then=Value(True)),
        default=Value(False),
        output_field=BooleanField(),
    )
)
like image 153
Alasdair Avatar answered Feb 13 '23 02:02

Alasdair