Django REST Framework按外键过滤GET请求(MultipleObjectsReturned错误)
解决指定用户关联Supplier的过滤问题
错误原因
你设置了lookup_field='user',当访问/pm/getsuppliers/{user_id}/时,ModelViewSet的retrieve详情视图会自动调用Supplier.objects.get(user=user_id)查询单条记录。但一个User对应多个Supplier,get()方法要求只能返回单个对象,因此触发MultipleObjectsReturned异常。
解决方案
方案1:使用查询参数过滤列表视图
修改views.py,重写get_queryset方法,通过URL查询参数过滤指定用户的Supplier:
class getsuppliers(viewsets.ModelViewSet): queryset = Supplier.objects.all() serializer_class = GetSuppliersSerializer def get_queryset(self): # 先获取基础查询集 queryset = super().get_queryset() # 从请求查询参数中获取user_id user_id = self.request.query_params.get('user_id') if user_id: # 过滤出该用户的所有Supplier queryset = queryset.filter(user_id=user_id) return queryset
访问方式:http://localhost:8000/pm/getsuppliers/?user_id=你的用户ID
方案2:自定义URL动作(符合REST路径风格)
如果希望用/pm/getsuppliers/user/{user_id}/这种路径访问,可通过DRF的@action装饰器添加自定义动作:
from rest_framework.decorators import action from rest_framework.response import Response class getsuppliers(viewsets.ModelViewSet): queryset = Supplier.objects.all() serializer_class = GetSuppliersSerializer @action(detail=False, url_path='user/(?P<user_id>[0-9]+)') def by_user(self, request, user_id=None): # 过滤指定用户的所有Supplier suppliers = Supplier.objects.filter(user_id=user_id) # 序列化多个对象需指定many=True serializer = self.get_serializer(suppliers, many=True) return Response(serializer.data)
访问方式:http://localhost:8000/pm/getsuppliers/user/你的用户ID/
关键说明
- 不要用
lookup_field='user'实现列表过滤:lookup_field是用于详情视图查找单条记录的字段,不适合一对多关联场景。 - 使用
filter()替代get():filter()会返回符合条件的所有对象(QuerySet),而get()仅返回单个对象,这正是批量查询需要的逻辑。
内容的提问来源于stack exchange,提问作者Kyle Andrew
相关产品推荐
相关产品推荐

