如果出现此问题会怎样? 请求对象没有属性“accepted_renderer”
这些消息在我的日志中。
基本视图集类:
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)
答案 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
的超级呼叫。