Reputation: 448
I have been thru endless posts on Django and the LEFT JOIN problem and but have not found anyone that has a solution in the 2.2 version of Django. Whilst in years past it seems there were ways to get around this problem, the Django team seem to have shut down every mechanism people have employed to achieve the most simple but necessary query - the LEFT JOIN. Here is a simle example of what I am trying to do (it is a simple example to reflect a real world scenario so please do not offer ways to redesign the models... all I want is the age old LEFT JOIN in SQL .... that simple):
from django.db import models
from uuid import uuid4
class People(models.Model):
id = models.UUIDField(primary_key=True, editable=False, default=uuid4)
name = models.CharField(max_length=255)
class Book(models.Model):
id = models.UUIDField(primary_key=True, editable=False, default=uuid4)
name = models.CharField(max_length=255)
author = models.ForeignKey(People)
publisher = models.ForeignKey(People, on_delete=models.PROTECT, null=True)
How would I achive an output showing all books and the publisher if there is a publisher (otherwise just blank)
Books.objects.filter(Q(publisher__isnull=True | Q(publisher__isnull=False)
... produces an INNER JOIN which will obviously only show books that have a publisher assigned. The query I am looking for would be of the form: select * from book LEFT JOIN people ON book.publisher_id=people.id
... or do I have to resort to raw SQL for this most simple of requirements?
Upvotes: 1
Views: 573
Reputation: 476768
You can perform a .select_related(..)
[Django-doc] here:
Book.objects.select_related('publisher')
This will fetch both the Book
data and the related Publisher
if it exists. So some_book.publisher
where some_book
originates from this queryset, will not result in an extra query to fetch the publisher. The query this will look like:
SELECT book.id, book.name, book.author_id, book.publisher_id,
people.id, people.name
FROM book
LEFT OUTER JOIN people ON book.publisher_id = people.id
Upvotes: 1