The exact query cannot be created using the Django ORM without resorting to some raw SQL. The problem is the OR in the join condition.
But, since your not selecting any rows from the user table, you can create a different query with the same results.
Start by defining your models using ForeignKeys.
from django.db import models
from django.contrib.auth.models import User
class Thread(models.Model):
last_message = models.TextField(max_length=100)
user1 = models.ForeignKey(User)
user2 = models.ForeignKey(User)
class Meta:
db_table = 'thread' # otherwise it will be: appname_thread
Then you can preform the query.
from django.db.models import Q
threads = Thread.objects.filter(Q(user1__id=9) | Q(user2__id=9))
The resulting SQL will be something like this:
SELECT * FROM thread
LEFT JOIN user AS user1
ON (thread.user1_id = user1.id)
LEFT JOIN user AS user2
ON (thread.user2_id = user2.id)
WHERE (user1.id = 9 OR user2.id = 9)
You can improve this by avoiding the join altogether.
# note the single underscore!
threads = Thread.objects.filter(Q(user1_id=9) | Q(user2_id=9))
Generating the following SQL.
SELECT * FROM thread
WHERE (user1_id = 9 OR user2_id = 9)
If you need to also obtain the user instances in the same query, in which case you really need the join, you have two options.
Either use the first query that includes joins and afterwards select the correct user based in the id in Python.
for thread in threads:
if thread.user1.id == 9:
user = thread.user1
else:
user = thread.user2
Or use raw SQL to get the exact query you want. In this case, you can use the models without the ForeignKeys as you defined them.
threads = Thread.objects.raw('''
SELECT *, user.id AS user_id, user.name as user_name FROM thread
LEFT JOIN user
ON (thread.user1_id = user.id OR thread.user2_id = user.id)
WHERE user.id = 9''')
for thread in threads:
# threads use the ORM
thread.id
# user fields are extra attributes
thread.user_id
thread.user_name