请求对象没有属性“accepted_renderer”

时间:2018-04-28 07:03:40

标签: django django-rest-framework

如果出现此问题会怎样? 请求对象没有属性“accepted_renderer”

这些消息在我的日志中。

  1. 处理此事件时遇到错误。
  2. 放弃参数'timestamp'的无效值展开
  3. 基本视图集类:

    class BaseViewSet(LoggingMixin, viewsets.ModelViewSet):
                def __init__(self, *args, **kwargs):
                    super(BaseViewSet, self).__init__(**kwargs)
    
                authentication_classes = (JSONWebTokenAuthentication, 
                                SessionAuthentication, BasicAuthentication)
                permission_classes = (IsAuthenticated,)
                renderer_classes = (JSONRenderer, BrowsableAPIRenderer, 
                             AdminRenderer,)
    
                def initial(self, request, *args, **kwargs):
                    user = request.user.baseuser
                    user.last_visit = datetime.datetime.now()
                    user.save()
                    super(LoggingMixin, self).initial(request, *args,**kwargs)
    

    我的api:

    api_v1_router.register(prefix=r'notify', viewset=NotificationViewSet, base_name='notify')
    

    我的观点:

    class NotificationViewSet(BaseViewSet):
    queryset = Notification.objects.all()
    serializer_class = NotificationSerializer
    
    def list(self, request, *args, **kwargs):
        queryset = self.queryset.filter(send_to_id=request.user.id, seen=False).order_by('-created_date')
    
        page = self.paginate_queryset(queryset)
        if page is not None:
            serializer = self.get_serializer(page, many=True)
            return self.get_paginated_response(serializer.data)
    
        serializer = self.get_serializer(queryset, many=True)
        return Response(serializer.data)
    

    我的setting.py:

    REST_FRAMEWORK = {
    # Use Django's standard `django.contrib.auth` permissions,
    # or allow read-only access for unauthenticated users.
    'DEFAULT_PERMISSION_CLASSES': [
        'rest_framework.permissions.DjangoModelPermissionsOrAnonReadOnly'
    ],
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
        'rest_framework.authentication.SessionAuthentication',
        'rest_framework.authentication.BasicAuthentication',
    ),
    'DEFAULT_FILTER_BACKENDS': (
        'django_filters.rest_framework.DjangoFilterBackend',
    ),
    'DEFAULT_RENDERER_CLASSES': (
        'rest_framework.renderers.JSONRenderer',
        'rest_framework.renderers.BrowsableAPIRenderer',
        'rest_framework.renderers.AdminRenderer',
    ),
    'DEFAULT_PAGINATION_CLASS':'apps.common.helpers.pagination.CustomPagination',
        'PAGE_SIZE': 12}
    

    回溯:

        AttributeError: 'WSGIRequest' object has no attribute 'accepted_renderer'
      File "rest_framework/request.py", line 382, in __getattribute__
        return getattr(self._request, attr)
    AttributeError: 'Request' object has no attribute 'accepted_renderer'
      File "django/core/handlers/exception.py", line 41, in inner
        response = get_response(request)
      File "django/core/handlers/base.py", line 187, in _get_response
        response = self.process_exception_by_middleware(e, request)
        response = super(BaseLoggingMixin, self).handle_exception(exc)
      File "rest_framework/views.py", line 449, in handle_exception
        self.raise_uncaught_exception(exc)
      File "rest_framework/views.py", line 457, in raise_uncaught_exception
        renderer_format = getattr(request.accepted_renderer, 'format')
      File "rest_framework/request.py", line 384, in __getattribute__
        six.reraise(info[0], info[1], info[2].tb_next)
      File "django/utils/six.py", line 685, in reraise
        raise value.with_traceback(tb)
    

2 个答案:

答案 0 :(得分:6)

在我的情况下,这是https://github.com/encode/django-rest-framework/issues/6300,但缺少pyyaml

答案 1 :(得分:2)

问题在于覆盖super内的def initial来电。您需要在BaseViewSet而非LoggingMixin上调用超级方法。

按如下方式更改超级行:

super(BaseViewSet, self).initial(request, *args,**kwargs)

这将确保执行所有相应的super来电;并确保APIView.initial来电;然后将accept_renderer属性设置如下:

APIView中的def initial方法(由ModelViewSet内部使用)是在accepted_renderer对象上设置Request属性的方法。这是源代码:

   def initial(self, request, *args, **kwargs):
        """
        Runs anything that needs to occur prior to calling the method handler.
        """
        self.format_kwarg = self.get_format_suffix(**kwargs)

        # Perform content negotiation and store the accepted info on the request
        neg = self.perform_content_negotiation(request)
        request.accepted_renderer, request.accepted_media_type = neg

        # Determine the API version, if versioning is in use.
        version, scheme = self.determine_version(request, *args, **kwargs)
        request.version, request.versioning_scheme = version, scheme

        # Ensure that the incoming request is permitted
        self.perform_authentication(request)
        self.check_permissions(request)
        self.check_throttles(request)

<强>买者

如果您在def initial内定义了LoggingMixin,答案会更改。如果你有;我想明白为什么;因为需要以某种方式满足对ModelViewset.initial的超级呼叫。