Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Annotating a Django queryset with a left outer join?

Tags:

django

Say I have a model:

class Foo(models.Model):     ... 

and another model that basically gives per-user information about Foo:

class UserFoo(models.Model):     user = models.ForeignKey(User)     foo = models.ForeignKey(Foo)     ...      class Meta:         unique_together = ("user", "foo") 

I'd like to generate a queryset of Foos but annotated with the (optional) related UserFoo based on user=request.user.

So it's effectively a LEFT OUTER JOIN on (foo.id = userfoo.foo_id AND userfoo.user_id = ...)

like image 991
James Tauber Avatar asked Jun 27 '11 23:06

James Tauber


People also ask

What is annotate in Django QuerySet?

annotate()that has been computed over the objects that are related to the objects in the QuerySet . Each argument to annotate() is an annotation that will be added to each object in the QuerySet that is returned. The aggregation functions that are provided by Django are described in Aggregation Functions below.

What is difference between annotate and aggregate Django?

Aggregate calculates values for the entire queryset. Annotate calculates summary values for each item in the queryset.

What is QuerySet annotate?

Appending the annotate() clause onto a QuerySet lets you add an attribute to each item in the QuerySet, like if you wanted to count the amount of articles in each category. However, sometimes you only want to count objects that match a certain condition, for example only counting articles that are published.

How do I join models in Django?

Join can be done with select_related method: Django defines this function as Returns a QuerySet that will “follow” foreign-key relationships, selecting additional related-object data when it executes its query.


1 Answers

A solution with raw might look like

foos = Foo.objects.raw("SELECT foo.* FROM foo LEFT OUTER JOIN userfoo ON (foo.id = userfoo.foo_id AND foo.user_id = %s)", [request.user.id]) 

You'll need to modify the SELECT to include extra fields from userfoo which will be annotated to the resulting Foo instances in the queryset.

like image 188
Brian Rosner Avatar answered Sep 22 '22 21:09

Brian Rosner