1

With the following model, I would like to select root users having the most posts in validated state (in a single query or at least in an optimized way). In my case root user are not directly authors, I want to aggregate children user authors on root users.

class User(models.Model):
    name = models.CharField(max_length=255)
    # root users have no root
    root = models.ForeignKey('User', blank=True, null=True)

class Post(models.Model):
    STATE_CHOICES = (
        (0, 'Writting'),
        (1, 'Reviewing'),
        (2, 'Validated'),
        (3, 'Published'),
        (4, 'Removed'),
    )
    state = models.IntegerField(choices=STATE_CHOICES, default=0)
    # authors are no root user
    author = models.ForeignKey('User')

# all validated but not published posts:
Post.objects.filter(state=2)

# all user having validated but not published posts:
User.objects.filter(post__state=2)

# same with number of posts
User.objects.filter(post__state=2).annotate(post_count=Count('post'))

# same ordered by number of posts
User.objects.filter(post__state=2).annotate(post_count=Count('post')).order_by('-post_count')

# same keeping only the top 10
User.objects.filter(post__state=2).annotate(post_count=Count('post')).order_by('-post_count')[:10]

# same aggregated for root users: NOT WORKING!
User.objects.filter(user__post__state=2).annotate(post_count=Count('post')).order_by('-post_count')[:10]  # FieldError: Cannot resolve keyword 'user' into field.
User.objects.filter(root__post__state=2).annotate(post_count=Count('post')).order_by('-post_count')[:10]  # no result

This issue may be related to the lack of backward relationship on a same model?

# works:
User.objects.filter(post__author=F('id'))

# not working:
User.objects.filter(user__root=F('id'))
srjjio
  • 930
  • 1
  • 8
  • 16
  • See http://stackoverflow.com/questions/38494989/mysql-self-join-full-table-scan-cannot-scan-index/38496552#38496552 and http://stackoverflow.com/questions/37287868/get-sum-from-nodes-tree/37288233#37288233 for an idea – e4c5 Jan 25 '17 at 12:40

0 Answers0