views:

254

answers:

2

so I have this model:

class Message(models.Model):
    creator = models.ForeignKey(User, unique=True)
    note = models.CharField(max_length=200, blank=True)
    recipients = models.ManyToManyField(User, related_name="shared_to")
    read = models.ManyToManyField(User, related_name="read", blank=True)

I want to filter on people who are in both recipients and read, currently I'm doing this.

messages = user.shared_to.all()

for message in messages:
    if user not in message.read:
        do something

I'm sure there is a way to filter this but I can't figure out how.

A: 

I think that I originally misread your question. Try the following query.

for message in user.shared_to.exclude(read__id__in=[user.id]):
  do_something()
mattkemp
A: 

If you use the Django development version, or wait until version 1.1 is released, then your filters can reference other fields in the model. So, your query would look like this:

>>> Message.objects.filter(reciepients=F('read'))

(Note: I spelled reciepients the same as you had in your model, although the correct spelling would be "recipients")

Edit:

Ok, your question is confusing. When I gave the above answer I was reading your statement that you wanted all users who were in both "recipients" and "read"). But then reading your code snippet it looks like you want a list of users who are recipients, but not yet in the "read" list.

This is probably what you want, but I'm not completely sure because of the vague requirements and I can't quickly test it:

# Get list of recipients
shared_to = Message.shared_to.all().values('id')

# Now list of recipients who are not in the read field
unread = Message.objects.exclude(recipients__in=shared_to)

This will make a single query, but if you are using MySQL it could still be more efficient to do two queries (read the Performance considerations warning).

Van Gale