I have the following three models where Budget and Sale both contain a foreign key to Customer:
class Customer(models.Model): name = models.CharField(max_length=45) # ... class Budget(models.Model): customer = models.ForeignKey(Customer, on_delete=models.PROTECT) # ... class Sale(models.Model): customer = models.ForeignKey(Customer, on_delete=models.PROTECT) # ...
I want to get a queryset of all Customer objects for which both a Budget and Sale exists. I initially tried getting the intersection of the customer field of all Budget and Sale objects:
customers = { budget.customer for budget in Budget.objects.all() } & { sale.customer for sale in Sale.objects.all() }
This returns the correct objects, but becomes horribly inefficient as the size of my database grows.
How can I retrieve these objects in a more efficient way? Thanks for any help!
Advertisement
Answer
You can filter with:
Customer.objects.filter( budget__isnull=False, sale__isnull=False ).distinct()
Django can follow ForeignKey
s in reverse. It uses the related_query_name=…
parameter [Django-doc] for the name of relation. If that is not specified, it falls back on the related_name=…
parameter [Django-doc] parameter, and if that is not specified, it will use the name of the model in lowercase, so budget
and sale
. We here make LEFT OUTER JOIN
s on the Budget
and Sale
table, and check if for both there is a non-null row. Likely the Django ORM will optimize this to INNER JOIN
s.