0

I am making a very minimal user-to-user messaging app using Django 1.4. I want to fetch unread messages that a user received in a straightforward way from my templates. My model looks something like this:

from django.contrib.auth.models import User

class Message(models.Model):
    sender = models.ForeignKey(User, related_name='messages_sent')
    receiver = models.ForeignKey(User, related_name='messages_received')
    read = models.BooleanField(default=False)

Now I can easily access the messages that a user has received from user.messages_received. I'd like to filter this queryset, though, to quickly access the unread messages in an easy way. I know that I can always filter the queryset user.messages_received.filter(read=False), but I'd like to get at them directly in templates, possibly like this:

<a href="{% url inbox %}"> Inbox ({{ user.unread_messages.count }})</a>

I suspect I want to make a Manager, but I'm not sure how to write it or where to attach it.

Thanks in advance.

jreyes
  • 143
  • 4

1 Answers1

1

There are two ways to accomplish this that come to my mind.

First, you could extend the user model with a custom function.

from django.contrib.auth.models import User

def unread_messages(self):
    return self.messages_received.filter(read=False)
User.add_to_class('unread_messages', unread_messages)

But that is slightly hacky. The "clean" way would be not to extend the User model directly, but to create a UserProfile for your users and add the function there. The docs describe this quite well.

In your case:

models.py

from django.db import models
from django.contrib.auth.models import User

class UserProfile(models.Model):
    user = models.OneToOneField(User)
    def unread_messages(self):
        return self.user.messages_received.filter(read=False)

settings.py

AUTH_PROFILE_MODULE = 'appname.UserProfile'

template

{{ user.get_profile.unread_messages.count }}

The code is untested, but should work :)

Danilo Bargen
  • 18,626
  • 15
  • 91
  • 127
  • Thanks, I can easily add that to my user profile model. I'm a little hesitant, though. My profile model is in a different app than my message app, and I was hoping not to mix the two. But this certainly works. – jreyes Apr 04 '12 at 23:19
  • You could also solve it via a custom template filter that gets the count for a user passed as the parameter. But I'm not sure whether that's a cleaner solution, probably not :) – Danilo Bargen Apr 05 '12 at 13:05
  • And if you decorate ``unread_messages`` with ``@property``, you do no longer need ``()`` for calling it and it will look a lot as if it were in fact a Manager. – Lutz Prechelt Apr 21 '16 at 08:27