请求对象没有属性"accepted_renderer"

roo*_*eki 4 django django-rest-framework

如果出现此问题会发生什么?请求对象没有属性"accepted_renderer"

这些消息在我的日志中.

  1. 处理此事件时遇到错误.
  2. 放弃参数'timestamp'的无效值展开

基本视图集类:

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)
Run Code Online (Sandbox Code Playgroud)

我的api:

api_v1_router.register(prefix=r'notify', viewset=NotificationViewSet, base_name='notify')
Run Code Online (Sandbox Code Playgroud)

我的观点:

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)
Run Code Online (Sandbox Code Playgroud)

我的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}
Run Code Online (Sandbox Code Playgroud)

追溯:

    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)
Run Code Online (Sandbox Code Playgroud)

rti*_*dru 7

问题在于super您覆盖def initial. 您需要在BaseViewSet而不是在上调用超级方法LoggingMixin

更改您的超级线路如下:

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

这将确保super执行所有相应的调用;并将确保进行APIView.initial呼叫;然后设置他accept_renderer属性设置如下:

def initialAPIView 中的方法(由 ModelViewSet 内部使用)是accepted_rendererRequest对象上设置属性的方法。这是源代码:

   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)
Run Code Online (Sandbox Code Playgroud)

警告

如果您定义了一个def initialinside ,答案就会改变LoggingMixin。如果你有; 我想知道为什么;因为ModelViewset.initial需要以某种方式满足超级调用。