解决TypeError:SearchProduct.get()收到意外关键字参数'query'问题
解决Django GenericAPIView接收query参数时的TypeError问题
问题核心
调用继承自GenericAPIView的SearchProduct视图时出现错误:TypeError: SearchProduct.get() got an unexpected keyword argument 'query',原因是URL路径中定义的<str:query>参数会被Django自动传递给视图的get方法,但当前get方法未声明接收该参数;同时前后端参数传递方式不统一,导致逻辑混乱。
解决方案(两种可选)
方案1:统一使用URL路径参数传递query
修改视图代码(product_views.py)
from django.db.models import Q from rest_framework.response import Response from rest_framework import status class SearchProduct(GenericAPIView): serializer_class = ProductSerializer pagination_class = CustomPagination1 def get_queryset(self, query=None, *args, **kwargs): # 优先使用路径传递的query,兼容GET参数方式 query = query or self.request.GET.get("query") if not query: # 无搜索词时返回空集合,可根据需求改为返回所有商品 return Product.objects.none() lookup = Q(name__icontains=query) | Q(description__icontains=query) | Q(producttag__title__icontains=query) return Product.objects.filter(lookup).distinct() def get(self, request, query): queryset = self.get_queryset(query=query) page = self.paginate_queryset(queryset) if page is not None: serializer = self.get_serializer(page, many=True) result = self.get_paginated_response(serializer.data) data = result.data else: serializer = self.get_serializer(queryset, many=True) data = serializer.data payload = { 'return_code': '0000', 'return_message': 'Success', 'data': data } return Response(payload, status=status.HTTP_200_OK)
关键修改点:
- 给
get方法添加query参数,接收URL路径传递的值 - 修复原代码中else分支
queryset未定义的错误 - 调整返回值为约定的
payload结构(原代码错误返回了原始分页/序列化数据)
方案2:统一使用URL查询参数传递query(推荐,符合RESTful规范)
搜索接口更适合用?query=xxx的查询参数方式,避免路径中包含特殊字符导致的解析问题。
修改URL配置(product_urls.py)
path('search_product/', views.SearchProduct.as_view(), name="search_product"),
修改视图代码(product_views.py)
from django.db.models import Q from rest_framework.response import Response from rest_framework import status class SearchProduct(GenericAPIView): serializer_class = ProductSerializer pagination_class = CustomPagination1 def get_queryset(self, *args, **kwargs): query = self.request.GET.get("query", "") if not query: return Product.objects.none() lookup = Q(name__icontains=query) | Q(description__icontains=query) | Q(producttag__title__icontains=query) return Product.objects.filter(lookup).distinct() def get(self, request): queryset = self.get_queryset() page = self.paginate_queryset(queryset) if page is not None: serializer = self.get_serializer(page, many=True) result = self.get_paginated_response(serializer.data) data = result.data else: serializer = self.get_serializer(queryset, many=True) data = serializer.data payload = { 'return_code': '0000', 'return_message': 'Success', 'data': data } return Response(payload, status=status.HTTP_200_OK)
修改前端请求(productAction.js)
用axios的params参数自动处理URL编码:
export const productsSearchAction = (query , pageNumber) => async (dispatch , getState) => { try { dispatch({type: PRODUCTS_SEARCH_REQUEST}); const {data} = await axios.get(`http://127.0.0.1:8000/api/v1/products/search_product/`, { params: { query: query, page: pageNumber } }); dispatch({type: PRODUCTS_SEARCH_SUCCESS , payload: data}); localStorage.setItem("productsSearch" , JSON.stringify(data)); } catch (error) { dispatch({ type: PRODUCTS_SEARCH_FAILED, payload: error.response && error.response.data.detail ? error.response.data.detail : error.message, }); } }
错误点总结
- 视图方法未接收路径参数:URL中定义的
<str:query>会被Django传递给get方法,方法未声明对应参数会触发TypeError - 变量未定义:原代码else分支中
queryset变量未声明,会导致NameError - 返回结构不符:原代码直接返回分页/序列化数据,未按约定返回包含
return_code的结构 - 参数传递不统一:前端同时用路径和查询参数传递值,后端仅从GET取query,逻辑混乱
内容的提问来源于stack exchange,提问作者saman barjawand
相关产品推荐
相关产品推荐

