如何通过反向关系获取多对多密钥的计数?

时间:2016-11-23 11:21:41

标签: django django-models django-admin

我希望我能就此得到你的建议。

如果我的披萨模型与浇头有多对多的关系,我可以轻松获得披萨上配料的数量。

# models.py
class Pizza(models.Model):
    toppings = models.ManyToManyField(Topping)

class Topping(models.Model):
    name = models.CharField(max_length=255, null=True, blank=True)

# admin.py
@admin.register(Pizza)
class PizzaAdmin(admin.ModelAdmin):
    list_display = ['topping_count']

    def topping_count(self, pizza):
        return pizza.toppings.count()

但是,如果我将多对多的前向关系移动到Topping,这一切都会中断。

# models.py
class Pizza(models.Model):
    pass

class Topping(models.Model):
    pizzas = models.ManyToManyField(Pizza)

如何在PizzaAdmin中更新topping_count,以便我能够通过反向关系获取浇头数?

谢谢。

3 个答案:

答案 0 :(得分:2)

反向关系使用小写的模型名称+ _set

@admin.register(Pizza)
class PizzaAdmin(admin.ModelAdmin):
    list_display = ['topping_count']

    def topping_count(self, pizza):
        return pizza.topping_set.count()

或者,您可以保留当前的管理员代码并更改相关名称:

class Topping(models.Model):
    pizzas = models.ManyToManyField(Pizza, related_name='toppings')

答案 1 :(得分:1)

将反向关系的计数设为pizza.topping_set.count()

答案 2 :(得分:1)

计算浇头的方式效率低下,因为它为每个浇头执行单独的数据库查询。我建议使用annotate

@admin.register(Pizza)
class PizzaAdmin(admin.ModelAdmin):
    list_display = ['topping_count']

    def get_queryset(self, request):
        qs = super(PizzaAdmin, self).get_queryset(request)
        return qs.annotate(topping_count=Count('topping_set'))            

    def topping_count(self, pizza):
        return pizza.topping_count

说明:annotate会为管理员中的每个topping_count设置Pizza。然后,您的PizzaAdmin.topping_count只会从实例中检索topping_count的值。

这样一来,它只会碰到你的数据库一次,而不管比萨饼的数量。