Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Request object has no attribute "accepted_renderer"

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)
like image 357
rmaleki Avatar asked Apr 28 '18 07:04

rmaleki


2 Answers

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.

like image 141
rtindru Avatar answered Nov 16 '22 22:11

rtindru


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

like image 6
andilabs Avatar answered Nov 16 '22 21:11

andilabs