基于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)
说明:
- 提取
get_queryset方法复用查询逻辑,避免重复代码 - POST请求从
request.data解析JSON中的ingredients参数 - GET请求从URL查询参数
ingredients获取ID列表(格式为逗号分隔字符串) - 两种请求均保留
distinct()去重逻辑,可按需添加额外过滤规则
额外提示
- 注意模型中
Ingridient的拼写(代码中存在ingridients与Ingridient的拼写差异,建议统一为ingredients和Ingredient,避免混淆) - 序列化器中建议显式指定字段,替代
fields="__all__",降低后续字段变更带来的风险
内容的提问来源于stack exchange,提问作者Vleo
相关产品推荐
相关产品推荐

