Как сделать аннотацию для внешнего ключа в Django?

Мне нужно заменить свойство _points на аннотацию, чтобы у меня была возможность сортировать записи в панели администратора Django по этому значению.

Моя модель:

class CustomUser(models.Model):
    inviter = models.ForeignKey('self', on_delete=models.SET_NULL, null=True, blank=True)

    @property
    def _points(self):
        res = CustomUser.objects.filter(inviter_id=self.id).count()
        return res 

Мой администратор:

class CustomUserAdmin(admin.ModelAdmin):
    list_display = ['created', 'updated']

    def get_queryset(self, request):
        qs = super(CustomUserAdmin, self).get_queryset(request)
        qs = qs.annotate(points=(HOW TO CALCULATE _points HERE?).order_by('points')
        return qs

Противоположным способом отношения inviter является отношение customuser, поэтому вы можете реализовать это как:

from django.db.models import Count

class CustomUserAdmin(admin.ModelAdmin):
    list_display = ['created', 'updated']

    def get_queryset(self, request):
        return super().get_queryset(request).annotate(
            points=Count('customuser')
        ).order_by('-points')

Однако, возможно, имеет смысл переименовать related_name=… [Django-doc] вашего inviter в invitees:

class CustomUser(models.Model):
    inviter = models.ForeignKey(
        'self',
        related_name='invitees',
        on_delete=models.SET_NULL,
        null=True,
        blank=True
    )

    @property
    def _points(self):
        return self.invitees.count()

тогда мы считаем это как:

class CustomUserAdmin(admin.ModelAdmin):
    list_display = ['created', 'updated']

    def get_queryset(self, request):
        return super().get_queryset(request).annotate(
            points=Count('invitees')
        ).order_by('-points')
Вернуться на верх