views:

278

answers:

2

I've got models like those in django:

class User(models.Model):
  name = models.CharField(max_length = 128)

class Message(models.Model):
  sender = models.ForeignKey(User, related_name = 'messages_sent')
  recipient = models.ForeignKey(User, related_name = 'messages_recieved')
  subject = models.CharField(max_length = 128)
  body = models.CharField(max_length = 3500)

class Response(models.Model):
  message = models.OneToOneField(Message, primary_key = True)
  reply = models.TextField()

and I'm trying to get all the messages for the user that have no response, something I would write in SQL as:

select * from user u
         join message m on (u.id = m.recipient_id)
         left join response r on (m.id = r.message_id)
where r.message_id = null

I'd think the natural way to do this would be:

u.messages_recieved.filter(response = None)

or

u.messages_recieved.filter(response__message_id__isnull = True)

but the SQL generated always ends up being:

WHERE ("project_message"."recipient_id" = 1  AND "project_message"."id" IS NULL)

Am I doing something stupid, or is this a bug in Django?

+2  A: 

Something that I've done when trying to achieve a similar result is:

u.messages_received.filter(~Q(response__id__gt=0))
Adam
+1  A: 

Try:

user.messages_recieved.filter(response__isnull=True)

the resulting query is:

SELECT "messaging_message"."id", "messaging_message"."sender_id", "messaging_message"."recipient_id", "messaging_message"."subject", "messaging_message"."body" FROM "messaging_message" LEFT OUTER JOIN "messaging_response" ON ("messaging_message"."id" = "messaging_response"."message_id") WHERE ("messaging_message"."recipient_id" = 1  AND "messaging_response"."message_id" IS NULL)

which I think is proper. It is indeed doing the left outer join and then checking for rows with null response message id.

u.messages_recieved.filter(response=None)

works fine too.

I'm using django 1.1 RC but this should work in 1.0+.

tarequeh
Hah! So it might be fixed in 1.1RC, as none of the above work for me in 1.0.2. Let me check.
tpk
So it was fixed in 1.1. Just tested on the final release of 1.1.
tpk
tarequeh