是否可以使用 django orm 按字段名称分组?

Is it possible to group by field name using django orm?

我有两个模型:

class ExampleOne(models.Model):
    # some fields
    
class ExampleTwo(models.Model):
    example_one = models.ForeignKey(
        "App.ExampleOne",
        on_delete=models.CASCADE,
        related_name="examples",
    )
    field_one = ...
    field_two = ...

我为我的端点创建了这个视图:

class MyViewSet(viewsets.ViewSet):
    def list(self, request):
        queryset = ExampleOne.objects.all().values(
            "id",
            "examples__field_one",
            "examples__field_two",
        )
        return Response({"data": queryset})

那个return这个:

{
  "data": [
    {
      "id": 1,
      "examples__id": 1,
      "examples__field_one": foo,
      "examples__field_two": bar,
    },
    {
    {
      "id": 1,
      "examples__id": 2,
      "examples__field_one": foo,
      "examples__field_two": bar,
    },
    {
      "id": 2,
      "examples__id": 3,
      "examples__field_one": foo,
      "examples__field_two": bar,
    }

但我想要一种按第一个模型分组的方法。这是可能的?我想要这样的东西:

{
  "data": [
    {
      "1": [
            {
            "examples__id": 1,
            "examples__field_one": foo,
            "examples__field_two": bar,
            },
            {
            "examples__id": 2,
            "examples__field_one": foo,
            "examples__field_two": bar,
            },      
      ],
      "2": [
            {
            "examples__id": 3,
            "examples__field_one": foo,
            "examples__field_two": bar,
            },      
      ]
    }
}

这可能吗?我找到的所有关于分组的信息都涉及值(计数、总和……)。但我只想按一个字段分组(模型一id)。

使用 Django ORM 没有直接的方法可以做到这一点。

使用原始 SQL

一个选项是使用原始 SQL 查询,但正如您指定的那样,您希望使用 ORM 实现此目的。

修改 query.group_by 属性

另一种方法是修改给定查询集的 querygroup_by 属性(这将大致翻译成 GROUP_BY SQL 语句):

qs = MyModel.objects.all()
qs.query.group_by = ['my_field']

这是推荐的,因为它没有记录在案API,它可能(会?)在您的查询集上做不需要的事情。

自己构建字典

另一种选择是不直接使用 ORM:

group_by_values = MyModel.objects.values_list(
    'group_by_field', flat=True
).distinct() # This is a list of all existing values for group_by_field

result = {
    value: MyModel.objects.filter(group_by_field=value)
    for value in group_by_values
}

第三方选项

最后一个选择是使用第三方库,例如 django-group-by

仅处理模板显示时(与您无关)

{% regroup %} 模板标签非常适合这个。参见 its docs

你可以做到


class ExampleOne(models.Model):
    # some fields
    
class ExampleTwo(models.Model):
    example_one = models.ForeignKey(
        "App.ExampleOne",
        on_delete=models.CASCADE,
        related_name="examples",
    )
    field_one = ManyToManyField(YourModel, related_name="*")
    field_two = ManyToManyField(YourModel, related_name="*")

或者您可以使用 for 循环

data = []
for i in yourmodel:
    dicts = {}
    dicts["id"] = i.id
    dicts["your_data"] = [{i.model_1}]
    data.append(dicts)
return Response({"data": data})

你可以试试这个:

queryset_data={}
for e in queryset:
  if e.value('id') not in new_data :
    new_data[e.value('id')]=[e.value("examples__id","examples__field_one","examples__field_two")]
  else :
    new_data[e.value('id')].append(e.value("examples__id","examples__field_one","examples__field_two"))
return Response({"data": queryset_data})