使用Django REST Framework构建函数式API时遭遇AssertionError及相关权限类、渲染器错误
解决你的Django REST Framework函数式API错误
嘿,我来帮你搞定这两个接连出现的问题!咱们一个个拆解来看:
第一个错误:Cannot apply DjangoModelPermissionsOrAnonReadOnly on a view that does not set .queryset or have a .get_queryset()
这个报错的核心原因很明确:你用的DjangoModelPermissionsOrAnonReadOnly权限类是为类视图设计的,它要求视图必须暴露queryset属性或者实现get_queryset()方法,这样权限系统才能判断用户对模型的操作权限。但你的函数视图里只是在内部定义了queryset变量,DRF的权限系统根本识别不到它。
有两种简单的解决办法:
方法1:给函数视图手动添加queryset属性
直接在函数外面补上这一行,让权限系统能找到对应的模型查询集:
@api_view(('GET',)) @renderer_classes((TemplateHTMLRenderer, JSONRenderer)) def course_api(request): if request.method == 'GET': queryset = Course.objects.all() serializer = CourseNameSerializers(queryset, many=True) return Response(serializer.data, template_name='api.html') # 手动添加queryset属性,让权限系统识别 course_api.queryset = Course.objects.all()
方法2:更换更适合函数视图的权限类
如果你不需要严格的模型级权限控制,直接换成IsAuthenticatedOrReadOnly或者AllowAny这类轻量化权限类就行。用@permission_classes装饰器指定即可:
from rest_framework.permissions import IsAuthenticatedOrReadOnly @api_view(('GET',)) @permission_classes([IsAuthenticatedOrReadOnly]) # 添加权限类装饰器 @renderer_classes((TemplateHTMLRenderer, JSONRenderer)) def course_api(request): if request.method == 'GET': queryset = Course.objects.all() serializer = CourseNameSerializers(queryset, many=True) return Response(serializer.data, template_name='api.html')
第二个错误:.accepted_renderer not set on Response
这个错误完全是因为你去掉了@api_view装饰器!DRF的Response对象依赖api_view装饰器完成一系列初始化工作:比如根据请求头选择合适的渲染器、设置accepted_renderer属性等。没有这个装饰器,Response根本不知道该怎么处理返回的数据,自然就报错了。
所以绝对不能去掉@api_view装饰器,它是函数视图能正常工作的核心。
把两个问题的解决方案结合起来,最终可运行的代码示例(以方法2为例)如下:
from rest_framework.decorators import api_view, renderer_classes, permission_classes from rest_framework.permissions import IsAuthenticatedOrReadOnly from rest_framework.renderers import TemplateHTMLRenderer, JSONRenderer from rest_framework.response import Response from .models import Course from .serializers import CourseNameSerializers @api_view(('GET',)) @permission_classes([IsAuthenticatedOrReadOnly]) @renderer_classes((TemplateHTMLRenderer, JSONRenderer)) def course_api(request): if request.method == 'GET': queryset = Course.objects.all() serializer = CourseNameSerializers(queryset, many=True) return Response(serializer.data, template_name='api.html')
内容的提问来源于stack exchange,提问作者Dhia Shalabi
相关产品推荐
相关产品推荐

