首页 > 解决方案 > 嵌套模型中的 Django REST Framework group by

问题描述

我是 Django REST 框架的新手。

我有一个用于保存餐厅订单的嵌套模型。当我发送 GET 请求时,我得到以下响应:

[
  {
    "menu": {
      "id": 1,
      "food_name": "food1"
    },
    "user": {
      "id": 49,
      "username": "A"
    }
  },
  {
    "menu": {
      "id": 1,
      "food_name": "food1"
    },
    "user": {
      "id": 63,
      "username": "B"
    }
  }
]

但我想用相同的菜单对用户进行分组,如下所示:

[
  {
    "menu": {
      "id": 1,
      "food_name": "food1",
      "users": {
        "1": {
          "id": 49,
          "username": "A"
        },
        "2": {
          "id": 63,
          "username": "B"
        }
      }
    }
  }
]

这是我的代码:

模型.py

class Order(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    menu = models.ForeignKey(Menu, on_delete=models.CASCADE)

视图.py

class OrderViewSet(viewsets.ModelViewSet):
    queryset = Order.objects.all()
    serializer_class = OrderSerializer

序列化程序.py

class OrderSerializer(serializers.HyperlinkedModelSerializer):
    user = UserSerializer()
    menu = MenuSerializer()
    class Meta:
        model = Order
        fields = ['id', 'user', 'menu']

谢谢

标签: pythondjangodjango-rest-framework

解决方案


由于您的输出表明您正在使用菜单,因此我建议您创建一个单独的视图集来使用菜单并在此处返回您想要的预期输出。

在 order viewset 中执行预期结果是可能的,但是使用select_relatedand进行优化是很棘手的prefetch_related。但是如果你真的想在你的订单视图中这样做,那么你可以这样做:

class MenuSerializer(serializers.ModelSerializer):
    users = serializers.SerializerMethodField()

    class Meta:
        model = Menu
        fields = ['id', 'food_name', 'users']

    def get_users(self, obj):
        users = User.objects.filter(pk__in=obj.order_set.all().values('user'))
        return UserSerializer(users, many=True).data


class OrderSerializer(serializers.HyperlinkedModelSerializer):
    menu = MenuSerializer()
    class Meta:
        model = Order
        fields = ['id', 'menu']

如果您想要不同的结果,您还需要更改视图的查询集,否则您将得到重复:

class OrderViewSet(viewsets.ModelViewSet):
    queryset = Order.objects.all().distinct('menu')
    serializer_class = OrderSerializer

请注意,这不是优化的,订单表中的每一行都需要访问数据库才能让用户通过菜单。distinct('menu')也仅适用于 PostgreSQL。


推荐阅读