Django+React花瓶检索项目REST API URL参数查询部分有效值失效
异常根因分析
1. 核心问题:全局异常捕获吞掉了查询错误
你的代码中对关联表查询用了裸except语句,会捕获所有类型的异常并直接跳过过滤逻辑,最终返回初始的全量数据集。触发异常的常见场景有两个:
- 关联表(Shape/Provenance/Collection/Artist)存在
shapeName/provenanceName等名称字段重复的记录,调用objects.get()查询时会抛出MultipleObjectsReturned异常,直接被捕获后跳过过滤 - 少数情况下URL参数传递时存在编码问题(比如特殊字符、空格未正确转义),导致参数值和数据库存储的值不一致,
get()抛出DoesNotExist异常被吞
2. 为什么部分参数正常?
当你传入的参数对应的名称在关联表中只有1条记录时,get()能正常返回对象,过滤逻辑生效,返回结果符合预期;一旦对应名称有2条及以上记录,就会触发异常跳过过滤,返回全量数据。
修复方案
- 禁止使用裸
except,明确捕获你需要处理的异常类型,同时可以加日志排查问题 - 建议直接用双下划线跨关联表查询,避免先查关联表再过滤的冗余逻辑,同时规避重复数据的问题
- 可选:给关联表的名称字段加唯一约束,从根源避免重复数据
修复后代码示例(views.py)
from django.core.exceptions import MultipleObjectsReturned, ObjectDoesNotExist import logging logger = logging.getLogger(__name__) class FilterVases(generics.ListAPIView): serializer_class = VaseSerializer def get_queryset(self): queryset = Vase.objects.all() query_provenance = self.request.query_params.get('provenance_name') if query_provenance is not None: # 直接跨表查询,不需要先查Provenance表 queryset = queryset.filter(provenance__provenanceName=query_provenance) inscription = self.request.query_params.get('inscription') if inscription is not None: queryset = queryset.filter(inscription=inscription) query_shape = self.request.query_params.get('shape_name') if query_shape is not None: queryset = queryset.filter(shape__shapeName=query_shape) query_collection = self.request.query_params.get('collection_name') if query_collection is not None: queryset = queryset.filter(collection__collectionName=query_collection) query_artist = self.request.query_params.get('artist_name') if query_artist is not None: queryset = queryset.filter(artist__artistName=query_artist) fabric = self.request.query_params.get('fabric') if fabric is not None: queryset = queryset.filter(fabric=fabric) vaseID = self.request.query_params.get('vaseID') if vaseID is not None: queryset = queryset.filter(vaseID=vaseID) return queryset
可选:给关联表加唯一约束(models.py)
class Shape(models.Model) : shapeID = models.CharField(max_length=10) shapeName = models.CharField(max_length=100, unique=True) # 加唯一约束 class Artist(models.Model) : artistID = models.CharField(max_length=10) artistName = models.CharField(max_length=100, unique=True) # 加唯一约束 class Provenance(models.Model) : ProvenanceID = models.CharField(max_length=10) provenanceName = models.CharField(max_length=100, unique=True) # 加唯一约束 class Collection(models.Model) : collectionID = models.CharField(max_length=10) collectionName = models.CharField(max_length=100, unique=True) # 加唯一约束
加完约束后执行makemigrations和migrate即可,后续入库重复名称会直接报错,避免脏数据。
内容的提问来源于stack exchange,提问作者EmilyCat111
相关产品推荐
相关产品推荐

