Request object has no attribute “accepted_renderer”

岁酱吖の 提交于 2021-01-27 03:51:00

问题


What happens if this problem occurs? Request object has no attribute "accepted_renderer"

These messages were in my log.

  1. There was error encountered while processing this event.
  2. Discarded invalid value for parameter 'timestamp' Expand

base viewset class:

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)

my api :

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

my viewset :

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)

my 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}

traceback:

    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)

回答1:


The problem lies in the super call within your override of def initial. You need to call the super method on the BaseViewSet and not on LoggingMixin.

Change your super line as follows:

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

This will ensure that all respective super calls are carried out; and will ensure that the APIView.initial call is made; which then setst he accept_renderer attribute as follows:

The def initial method in the APIView (which is used internally by ModelViewSet) is the one that sets the accepted_renderer attribute on the Request object. Here's the source code:

   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)

Caveat

The answer changes if you have defined a def initial inside LoggingMixin. If you have; I'd like to understand why; since the super call to ModelViewset.initial needs to be satisfied somehow.




回答2:


In my case this was https://github.com/encode/django-rest-framework/issues/6300 and missing pyyaml



来源:https://stackoverflow.com/questions/50073864/request-object-has-no-attribute-accepted-renderer

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!