You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于ManyToManyField获取Meal对象重复及API接口优化问题

问题解决:多对多关联查询重复数据与视图优化

一、解决Meal查询结果重复的问题

多对多关联查询时,若一个Meal同时关联多个传入的Ingredient,数据库会返回多条重复的Meal记录。只需在查询集后添加distinct()方法去重:

修改views.py中的post方法:

class TestCraft(APIView):
    def post(self, request):
        ingridients_tmp = request.data['ingredients']
        ingrid = Ingridient.objects.filter(id__in=ingridients_tmp)
        # 添加distinct()去重
        queryset = Meal.objects.filter(ingridients__in=ingrid).distinct()
        serializer = MealSerializer(queryset, many=True)
        return Response(serializer.data)

二、优化视图支持GET和POST请求

要让同一路径同时支持POST(接收JSON参数)和GET(通过Axios传递查询参数),只需在TestCraft类中添加get方法,统一提取查询逻辑复用:

class TestCraft(APIView):
    def get_queryset(self, ingredient_ids=None):
        # 公共查询逻辑,减少重复代码
        queryset = Meal.objects.all()
        if ingredient_ids:
            queryset = queryset.filter(ingridients__in=ingredient_ids).distinct()
        # 可按需添加过滤条件,比如只返回已发布的餐品
        queryset = queryset.filter(is_published=True)
        return queryset

    def post(self, request):
        # 处理POST请求:从JSON body获取ingredients数组
        ingridients_tmp = request.data.get('ingredients', [])
        queryset = self.get_queryset(ingridients_tmp)
        serializer = MealSerializer(queryset, many=True)
        return Response(serializer.data)

    def get(self, request):
        # 处理GET请求:从URL查询参数获取ingredients(格式如?ingredients=1,2)
        ingredients_param = request.query_params.get('ingredients', '')
        ingredient_ids = [int(id_str) for id_str in ingredients_param.split(',') if id_str.strip()]
        queryset = self.get_queryset(ingredient_ids)
        serializer = MealSerializer(queryset, many=True)
        return Response(serializer.data)

说明:

  1. 提取get_queryset方法复用查询逻辑,避免重复代码
  2. POST请求从request.data解析JSON中的ingredients参数
  3. GET请求从URL查询参数ingredients获取ID列表(格式为逗号分隔字符串)
  4. 两种请求均保留distinct()去重逻辑,可按需添加额外过滤规则

额外提示

  • 注意模型中Ingridient的拼写(代码中存在ingridients与Ingridient的拼写差异,建议统一为ingredients和Ingredient,避免混淆)
  • 序列化器中建议显式指定字段,替代fields="__all__",降低后续字段变更带来的风险

内容的提问来源于stack exchange,提问作者Vleo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 23:25:17