Django REST Framework APIView的post方法查全量数据仅返回单个对象如何解决
问题原因
post方法存在逻辑流程错误:for循环遍历ScrapyItem查询集时,无论第一个元素是否匹配传入的domain,都会直接触发return返回响应,循环仅会执行第一次迭代就终止,永远不会遍历后续的数据库条目:
- 如果第一个元素domain匹配,直接返回200成功
- 如果第一个元素domain不匹配,直接进入else分支返回400错误,后续所有条目都不会被校验
因此会出现查询全量数据但永远只能拿到单个对象判断结果的问题。
修复方案
基础修复(仅调整逻辑顺序,不改原有遍历逻辑)
把不匹配时的return逻辑移到for循环外部,等所有条目遍历完成仍没有匹配项时再返回错误:
class ScrapyViewSet(APIView): def get(self, request, format=None): snippets = ScrapyItem.objects.all() serializer = ScrapySerializer(snippets, many=True) return Response(serializer.data) def post(self, request): snippets = ScrapyItem.objects.all() domain = request.data['domain'] print(domain) for i in snippets: print(i) if i.domain == domain: return Response({"status": "success", "data": str(i.data)}, status=status.HTTP_200_OK) # 遍历完所有条目都没有匹配时才返回错误 return Response({"status": "error", "data": 'error'}, status=status.HTTP_400_BAD_REQUEST)
优化方案(推荐,避免全表遍历提升性能)
不需要手动遍历全量数据,直接用Django ORM的filter方法直接查询匹配条目,减少内存占用和查询耗时:
def post(self, request): domain = request.data['domain'] # 直接查询匹配domain的条目,存在就返回,不存在返回错误 matched_item = ScrapyItem.objects.filter(domain=domain).first() if matched_item: return Response({"status": "success", "data": str(matched_item.data)}, status=status.HTTP_200_OK) return Response({"status": "error", "data": 'error'}, status=status.HTTP_400_BAD_REQUEST)
内容的提问来源于stack exchange,提问作者Mahesh Krishnan
相关产品推荐
相关产品推荐

