7

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?

2
  • That sounds more like a template design thing.. Do you not need to check there if the message sender is the one looking at it? Commented Jan 27, 2016 at 17:42
  • That can be checked in the view through the request. Commented Jan 27, 2016 at 17:47

1 Answer 1

12

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(),
    )
)
Sign up to request clarification or add additional context in comments.

2 Comments

Note that support for conditional expressions is introduced in Django 1.9. docs.djangoproject.com/en/1.9/ref/models/…
@pygeek I thought they were new in 1.8, which is now the minimum supported version.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.