如何在Django REST Framework中通过URL查询参数获取模型字段值?
问题分析与解决
核心错误原因
- 'Account' object is not iterable:
ModelViewSet的get_queryset方法要求返回可迭代的QuerySet对象,但你用Account.objects.get(...)返回了单个Account实例,框架尝试遍历该实例时抛出错误。 - filter返回空列表:
request.query_params获取的参数是字符串类型,而数据库中user和account的主键是整数,类型不匹配导致查询无结果。
解决方案
方案一:调整ModelViewSet实现(适配原有视图结构)
1. 修正视图类(view.py)
将参数转为整数,用filter返回QuerySet,同时处理参数异常情况:
class TotalAssetsValueView(viewsets.ModelViewSet): serializer_class = TotalAssetsValueSerializer http_method_names = ['get'] def get_queryset(self): user_id = self.request.query_params.get('user') account_id = self.request.query_params.get('account') queryset = Account.objects.all() if user_id and account_id: try: # 字符串转整数,匹配数据库主键类型 user_id = int(user_id) account_id = int(account_id) queryset = queryset.filter(pk=account_id, user_id=user_id) except ValueError: # 参数非整数时返回空QuerySet queryset = queryset.none() return queryset
2. 修正序列化器(serializer.py)
total_value是模型方法而非数据库字段,需要用SerializerMethodField处理序列化:
class TotalAssetsValueSerializer(serializers.ModelSerializer): total_value = serializers.SerializerMethodField() class Meta: model = Account fields = ('total_value',) def get_total_value(self, obj): return obj.total_value()
方案二:改用APIView(更贴合单值返回需求)
如果仅需返回单个浮点数,用APIView更简洁,无需依赖ModelViewSet的复杂逻辑:
1. 修改视图类(view.py)
from rest_framework.views import APIView from rest_framework.response import Response from rest_framework import status class TotalAssetsValueView(APIView): def get(self, request): user_id = request.query_params.get('user') account_id = request.query_params.get('account') if not user_id or not account_id: return Response({"error": "缺少user或account参数"}, status=status.HTTP_400_BAD_REQUEST) try: user_id = int(user_id) account_id = int(account_id) account = Account.objects.get(pk=account_id, user_id=user_id) return Response({"total_value": account.total_value()}) except (ValueError, Account.DoesNotExist): return Response({"error": "找不到对应的Account记录"}, status=status.HTTP_404_NOT_FOUND)
2. 修改urls.py
改用APIView后无需router注册,直接配置路径:
urlpatterns = [ path('api/widget/total/', TotalAssetsValueView.as_view(), name='account-total'), ]
测试验证
请求URL:https://mysite/api/widget/total/?user=1&account=1
返回结果:
{"total_value": 1.22222344}
内容的提问来源于stack exchange,提问作者Florent
相关产品推荐
相关产品推荐

