Annotating a Django queryset with a left outer join?

前端 未结 10 761
予麋鹿
予麋鹿 2020-12-14 01:06

Say I have a model:

class Foo(models.Model):
    ...

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

10条回答
  •  被撕碎了的回忆
    2020-12-14 01:44

    This answer might not be exactly what you are looking for but since its the first result in google when searching for "django annotate outer join" so I will post it here.

    Note: tested on Djang 1.7

    Suppose you have the following models

    class User(models.Model):
        name = models.CharField()
    
    class EarnedPoints(models.Model):
        points = models.PositiveIntegerField()
        user = models.ForgeinKey(User)
    

    To get total user points you might do something like that

     User.objects.annotate(points=Sum("earned_points__points"))
    

    this will work but it will not return users who have no points, here we need outer join without any direct hacks or raw sql

    You can achieve that by doing this

     users_with_points = User.objects.annotate(points=Sum("earned_points__points"))
     result = users_with_points | User.objects.exclude(pk__in=users_with_points)
    

    This will be translated into OUTER LEFT JOIN and all users will be returned. users who has no points will have None value in their points attribute.

    Hope that helps

提交回复
热议问题