Django-rest-framework: 3.9: AttributeError when Schema Endpoint requires authentication

Created on 19 Oct 2018  路  9Comments  路  Source: encode/django-rest-framework

Checklist

  • [x] I have verified that that issue exists against the master branch of Django REST framework.
  • [x] I have searched for similar issues in both open and closed tickets and cannot find a duplicate.
  • [x] This is not a usage question. (Those should be directed to the discussion group instead.)
  • [x] This cannot be dealt with as a third party library. (We prefer new functionality to be in the form of third party libraries where possible.)
  • [x] I have reduced the issue to the simplest possible case.
  • [ ] I have included a failing test as a pull request. (If you are unable to do so we can still accept the issue.)

Steps to reproduce

from rest_framework.schemas import get_schema_view

schema_view = get_schema_view(
    title='Server Monitoring API',
    url='https://www.example.org/api/'
)

urlpatterns = [
    url('^schema.json$', schema_view),
]
  • Set Permission IsAuthenticated:
REST_FRAMEWORK = {
    'DEFAULT_PERMISSION_CLASSES': (
        'rest_framework.permissions.IsAuthenticated',
    ),
  • Open /schema.json

Expected behavior

  • Authorization Error

Actual behavior

Internal Server Error: /schema.json
Traceback (most recent call last):
  File "./.venv/lib/python3.6/site-packages/django/core/handlers/exception.py", line 35, in inner
    response = get_response(request)
  File "./.venv/lib/python3.6/site-packages/django/core/handlers/base.py", line 158, in _get_response
    response = self.process_exception_by_middleware(e, request)
  File "./.venv/lib/python3.6/site-packages/django/core/handlers/base.py", line 156, in _get_response
    response = response.render()
  File "./.venv/lib/python3.6/site-packages/django/template/response.py", line 106, in render
    self.content = self.rendered_content
  File "./.venv/lib/python3.6/site-packages/rest_framework/response.py", line 72, in rendered_content
    ret = renderer.render(self.data, accepted_media_type, context)
  File "./.venv/lib/python3.6/site-packages/rest_framework/renderers.py", line 732, in render
    context = self.get_context(data, accepted_media_type, renderer_context)
  File "./.venv/lib/python3.6/site-packages/rest_framework/renderers.py", line 687, in get_context
    'content': self.get_content(renderer, data, accepted_media_type, renderer_context),
  File "./.venv/lib/python3.6/site-packages/rest_framework/renderers.py", line 423, in get_content
    content = renderer.render(data, accepted_media_type, renderer_context)
  File "./.venv/lib/python3.6/site-packages/rest_framework/renderers.py", line 1036, in render
    structure = self.get_structure(data)
  File "./.venv/lib/python3.6/site-packages/rest_framework/renderers.py", line 1016, in get_structure
    'title': data.title,
AttributeError: 'dict' object has no attribute 'title'
.venv/lib/python3.6/site-packages/rest_framework/renderers.py in get_structure
data = {'detail': ErrorDetail(string='Authentication credentials were not provided.', code='not_authenticated')}

Schema Generation

All 9 comments

I'm having the same issue after upgrading to 3.9. Am able to work around the issue by logging by other means, but the schema view results in the following error:

```Traceback (most recent call last):
File "/Users/.../anaconda3/envs/datjango/lib/python3.6/site-packages/django/core/handlers/exception.py", line 34, in inner
response = get_response(request)
File "/Users/.../anaconda3/envs/datjango/lib/python3.6/site-packages/django/core/handlers/base.py", line 156, in _get_response
response = self.process_exception_by_middleware(e, request)
File "/Users/.../anaconda3/envs/datjango/lib/python3.6/site-packages/django/core/handlers/base.py", line 154, in _get_response
response = response.render()
File "/Users/.../anaconda3/envs/datjango/lib/python3.6/site-packages/django/template/response.py", line 106, in render
self.content = self.rendered_content
File "/Users/.../anaconda3/envs/datjango/lib/python3.6/site-packages/rest_framework/response.py", line 72, in rendered_content
ret = renderer.render(self.data, accepted_media_type, context)
File "/Users/.../anaconda3/envs/datjango/lib/python3.6/site-packages/rest_framework/renderers.py", line 732, in render
context = self.get_context(data, accepted_media_type, renderer_context)
File "/Users/.../anaconda3/envs/datjango/lib/python3.6/site-packages/rest_framework/renderers.py", line 687, in get_context
'content': self.get_content(renderer, data, accepted_media_type, renderer_context),
File "/Users/.../anaconda3/envs/datjango/lib/python3.6/site-packages/rest_framework/renderers.py", line 423, in get_content
content = renderer.render(data, accepted_media_type, renderer_context)
File "/Users/.../anaconda3/envs/datjango/lib/python3.6/site-packages/rest_framework/renderers.py", line 1036, in render
structure = self.get_structure(data)
File "/Users/.../anaconda3/envs/datjango/lib/python3.6/site-packages/rest_framework/renderers.py", line 1016, in get_structure
'title': data.title,
AttributeError: 'dict' object has no attribute 'title'

I duplicated the error with a clean install of Django==2.1.2 and djangorestframework==3.9.0 with "urls.py" as:

from django.contrib import admin
from django.urls import path, include
from rest_framework.schemas import get_schema_view
from rest_framework.renderers import JSONOpenAPIRenderer

schema_view = get_schema_view(
title='Server Monitoring API',
url='https://www.example.org/api/',
renderer_classes=[JSONOpenAPIRenderer]
)

urlpatterns = [
path('admin/', admin.site.urls),
path('api-auth/', include('rest_framework.urls')),
path('api/', get_schema_view()),
]
```
Let me know if there is any info I can provide to help.

Thanks for the minimal reproduction and traceback.

cc @carltongibson?

OK, so yes...

This looks to me like a variant of the same issue that came up with 3.6, when we introduced the interactive docs. Basically (I guess) the schema view is picking up DEFAULT_AUTHENTICATION_CLASSES. See e.g. #5399, #5309, #5448...

get_schema_view() takes authentication_classes. First this would be to try passing an empty list in there...

(Does that help?)

Is this a duplicate of #6258?

@carltongibson this is #6258 馃槃

Brough you this 鈽曪笍

... this is #6258 馃槃

Thought it looked relevant.

Brough you this 鈽曪笍

Thanks!

For those that are stuck here, you can just pass the AllowAny permission to the schema_view as a workaround.

schema_view = get_schema_view(
    title="My API",
    permission_classes=[rest_framework.permissions.AllowAny],
)

FYI, I'm still stuck here. I have a custom permission class that doesn't require authentication, so the workaround proposed by @devsnd doesn't work for me. As another alternative fix, I override the default renderer:

from rest_framework import exceptions, renderers

class OpenAPIRendererV2(renderers.OpenAPIRenderer):
    # temporary fix for: https://github.com/encode/django-rest-framework/issues/6258
    def get_structure(self, data):
        if "detail" in data and isinstance(data["detail"], exceptions.ErrorDetail):
            return {"errror": str(data["detail"])}
        return super().get_structure(data)
Was this page helpful?
0 / 5 - 0 ratings