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 Foo
s 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 = ...)
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.
Aggregate calculates values for the entire queryset. Annotate calculates summary values for each item in the queryset.
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.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With