Django按模型Meta中的注释排序

Spi*_*oni 2 django django-models

有没有办法通过带注释的字段在模型元类中设置排序?

IE

class ModelA(models.Model):
    name = models.CharField()

class ModelB(models.Model):
    name    = models.CharField()
    model_a = models.ForeignKey(ModelA)

Run Code Online (Sandbox Code Playgroud)

这就是我可以为 queryset 做的事情,但如果可能的话,需要在类 Meta 上做同样的事情

ModalA.objects.all()
      .annotate(
          count_b=Count("modal_a")
      )
      .order_by("count_b")

Run Code Online (Sandbox Code Playgroud)

Wil*_*sem 5

您可以将.objects经理覆盖到痛处,因此:

class ModelAManager(models.Manager):

    def get_queryset(self, *args, **kwargs):
        return super().get_queryset(*args, **kwargs).annotate(
            count_b = Count('modelb')
        ).order_by('count_b')
Run Code Online (Sandbox Code Playgroud)

然后将其注册为的经理ModelA

class ModelA(models.Model):
    # …
    objects = ModelAManager()
Run Code Online (Sandbox Code Playgroud)

话虽如此,我会按您需要的视图中的计数进行排序,而不是一般情况下,在这里您创建一个LEFT OUTER JOIN,但这意味着如果您通过过滤、注释等进行额外的连接,则这两个(或更多)JOINs 将相互影响,从而作为其他LEFT OUTER JOINs的乘数。

因此,ModelB在必要时简单地按相关s的数量排序可能会更好。

我们还可以向 中添加一个方法,以便通过一个方法Queryset进行排序count_b

class ModelAQueryset(models.QuerySet):
    def order_by_b(self):
        return self.annotate(
            count_b=Count('modelb')
        ).order_by('count_b')
Run Code Online (Sandbox Code Playgroud)

然后我们根据以下内容定义经理ModelAQueryset

class ModelA(models.Model):
    # …
    objects = ModelAQueryset.as_manager()
Run Code Online (Sandbox Code Playgroud)

然后您可以订购b

ModelA.objects.order_by_b()
Run Code Online (Sandbox Code Playgroud)

因此,您可以.order_by_b()在构建查询集的链中的任何部分调用查询集。