Override get_serializer_class for any view that inherits from GenericAPIView and attempt to access the request attribute when using the new SchemaGenerator, or going through DefaultRouter.
The request attribute is passed into SchemaGenerator initialisation and subsequent methods have access to it.
AttributeError: '<view-name>' object has no attribute 'request'
I was trying to write a test case for #4265 and ended up here.
Worth adding this also applies to the kwargs attribute.
Happening for me as well for 'kwargs'.
@rainyday @geekashu Not 100% clear what you folks are referring too. This?... #4359
@tomchristie Following is my view code for UserDetailView
class UserDetailView(RetrieveUpdateAPIView):
def get_serializer_class(self):
if (self.get_object() == self.request.user) or self.request.user.is_staff:
return UserDetailSerializer
else:
return UserPublicDetailSerializer
permission_classes = (IsProfileOwnerOrReadOnly,)
def get_object(self):
pk = self.kwargs.get('pk', None)
if not pk or (pk == str(self.request.user.pk)):
obj = self.request.user
else:
try:
obj = get_object_or_404(User, id=pk)
except ValueError:
obj = get_object_or_404(User, username=pk)
self.check_object_permissions(self.request, obj)
return obj
Schema generation is failing with following stacktrace...
Traceback (most recent call last):
File "/home/ashish/Env/backend/lib/python3.4/site-packages/django/core/handlers/base.py", line 149, in get_response
response = self.process_exception_by_middleware(e, request)
File "/home/ashish/Env/backend/lib/python3.4/site-packages/django/core/handlers/base.py", line 147, in get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/home/ashish/Env/backend/lib/python3.4/site-packages/django/views/decorators/csrf.py", line 58, in wrapped_view
return view_func(*args, **kwargs)
File "/home/ashish/Env/backend/lib/python3.4/site-packages/django/views/generic/base.py", line 68, in view
return self.dispatch(request, *args, **kwargs)
File "/home/ashish/Env/backend/lib/python3.4/site-packages/rest_framework/views.py", line 466, in dispatch
response = self.handle_exception(exc)
File "/home/ashish/Env/backend/lib/python3.4/site-packages/rest_framework/views.py", line 463, in dispatch
response = handler(request, *args, **kwargs)
File "/home/ashish/Env/backend/lib/python3.4/site-packages/rest_framework/decorators.py", line 52, in handler
return func(*args, **kwargs)
File "/home/ashish/Projects/backend/demoproject/config/swagger.py", line 18, in schema_view
generator = schemas.SchemaGenerator(title='DemoProject APIs')
File "/home/ashish/Env/backend/lib/python3.4/site-packages/rest_framework/schemas.py", line 78, in __init__
self.endpoints = self.get_api_endpoints(patterns)
File "/home/ashish/Env/backend/lib/python3.4/site-packages/rest_framework/schemas.py", line 132, in get_api_endpoints
prefix=path_regex
File "/home/ashish/Env/backend/lib/python3.4/site-packages/rest_framework/schemas.py", line 125, in get_api_endpoints
link = self.get_link(path, method, callback)
File "/home/ashish/Env/backend/lib/python3.4/site-packages/rest_framework/schemas.py", line 202, in get_link
fields += self.get_serializer_fields(path, method, callback, view)
File "/home/ashish/Env/backend/lib/python3.4/site-packages/rest_framework/schemas.py", line 268, in get_serializer_fields
serializer_class = view.get_serializer_class()
File "/home/ashish/Projects/backend/demoproject/users/views/user.py", line 35, in get_serializer_class
if (self.get_object() == self.request.user) or self.request.user.is_staff:
File "/home/ashish/Projects/backend/demoproject/users/views/user.py", line 43, in get_object
pk = self.kwargs.get('pk', None)
AttributeError: 'UserDetailView' object has no attribute 'kwargs'
I think this may be related with issue described above. Schema generation is not working for me even if request attribute is not passed. I did checked with latest build i.e 3.4.3.
I'm getting the same issue as @geekashu about not having self.kwargs available. Same problem with self.action when dynamically switching serializers in get_serializer_class().
Not 100% clear what you folks are referring too
To be slightly more specific as to what the issue is (we're now running into it)...
The schema generator is attempting to create a view which it can use for introspection, but the view is missing some of the attributes that we've come to expect when using generic method. One of those attributes is request, which usually points to the current request that is being processed by the view. A major use case for looking at view.request is to get the current user, view.request.user, so that the view processing logic can be switched based on who is making the request.
It's also been noted that view.action is also not set, which is the recommended way to change the serializer used within a view based on the action that is being taken. So having a different serializer for list vs detail views.
My issue is partially related to this one.
We have similar issue - we have custom permission system for nested routes which also is based on view's kwargs. And currently all those views are ignored by the schema generator.
Basically there are 2 problems:
request passed to the permission class is original request (to documentation endpoint), so it has same path and method for all views. So, our fallback for permissions which generates action from path and method doesn't work. For some views we can use generic viewset + mixins instead of generic views and this will solve this problem partially./parent-resource/<id>/resource/, don't work as well. In our case, because dispatch method (which sets some view's attr) of the view isn't invoked. And view's kwargs is empty. I understand that kwargs can't contain any values when inspecting views, but in this case all those endpoints are just ignored (since permissions return false).Is there a correct/supported way to show those endpoints in generated documentation?
@Alexx-G From the sound of it, it looks like you'd need to be providing a manual specified schema, or at least create an AutoSchema subclass that knows how to fill in the blanks. Set the right path on the request; add missing attrs, etc.
Maybe you could override SchemaGenerator.create_view() to provide more details — but again, exactly what you'd need to provide there isn't clear from your example. (Personally I'd prefer whatever adjustments to the view are needed the AutoSchema inspector, rather than the generator, but, as ever, you could do it in either place.)
In general, it's difficult to see how we can take out the path parameters (say). Whatever logic you have for schema generation is going to need to be handle that.
@carltongibson Thank you for the answer.
Yep, after spending some time in DRF docs/sources I reached same conclusion.
I think a custom AutoSchema would work in my case.
Is there a way to apply a custom AutoSchema class to all views (just as DEFAULT_* settings)? I didn't find anything similar in docs.
You’ll need to create a base view class (or mixin maybe) if you want to use it universally
Most helpful comment
@tomchristie Following is my view code for UserDetailView
Schema generation is failing with following stacktrace...
I think this may be related with issue described above. Schema generation is not working for me even if request attribute is not passed. I did checked with latest build i.e 3.4.3.