Django摘要查询

时间:2018-08-02 06:07:14

标签: django django-admin

在Django中是否可以为相关模型编写查询,以按位置分组汇总摘要,对象数量和相关对象的数量?

例如:

使用型号

class Job(models.Model):
    id_number = models.CharField()
    location = models.CharField()

class Item(models.Model):
    id_number = models.CharField()
    description = models.CharField()
    job = models.ForeignKey(Job)

如果我想获得一个admin.model来按位置对作业进行分组并显示每个位置的项目总数

| Location | Number of Jobs | Number of Items |
-----------------------------------------------
| Chicago  |      52        |      305       |
| Seattle  |      12        |      185       |    

等,

我曾尝试使用聚集和注释查询,但是这些似乎总是只能在计数的列之一准确或位置未分组/不拆分的情况下使用。我觉得这在Django中应该很简单,但是ORM却被大脑打破了...

我尝试了如下所示的admin.model,但这会分割位置...

@admin.register(JobSummary)
class JobSummaryAdmin(admin.ModelAdmin):
    list_display = ("location", "job_count", "item_count")

    def get_queryset(self, request):
        queryset = super().get_queryset(request)

        queryset = queryset.annotate(
            _job_count=Count("id",  distinct=True),
            _item_count=Count("item", distinct=True),
        )
        return queryset

    def job_count(self, obj):
        return obj._job_count

    def item_count(self, obj):
        return obj._item_count

谢谢您的建议

Han

1 个答案:

答案 0 :(得分:1)

聚合仅适用于自然查询集。由于您的位置字段是自由格式的CharField,因此无法围绕它构建查询集。首先,您需要将Location分解成自己的模型。

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

class Job(models.Model):
    id_number = models.CharField()
    models.ForeignKey(Location)

class Item(models.Model):
    id_number = models.CharField()
    description = models.CharField()
    job = models.ForeignKey(Job)

然后,您可以查询用新字段注释的位置

@admin.register(Location)
class LocationAdmin(admin.ModelAdmin):
    list_display = ("name", "job_count", "item_count")

    def get_queryset(self, request):
        queryset = super().get_queryset(request)

        queryset = queryset.annotate(
            _job_count=Count("job_set", distinct=True),
            _item_count=Count("job_set__item_set", distinct=True),
        )
        return queryset

    def job_count(self, obj):
        return obj._job_count

    def item_count(self, obj):
        return obj._item_count