-
Notifications
You must be signed in to change notification settings - Fork 273
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
Using DRF spectacular #705
Comments
Hi @rvanlaar, thanks alot.
the default is not fixed. spectacular will estimate the greatest common divider, remove it and then use the next URL item as the tag, e.g. if all endpoints are prefixed with
You need to make sure components have a unique name. Among other things you can influence the name with
YES, this happens automatically if proper
we have some support for dataclasses. mileage may vary.
this is an open feature request. Currently you have to set those error cases by hand via decorator |
Hi @tfranzel Thanks for your thoughtful response.
We indeed have two endpoints outside the /api/v1/ path. The SCHEMA_PATH_PREFIX is awesome. Now I can remove 80% of the manual tags I placed. We have some parts of the application that use a different prefix e.g. /api/v1/personal/ and /api/v1/student/ They now get grouped under one tag 'personal' and 'student'.
I don't quite understand. I created some example code: https://gist.github.com/rvanlaar/4a99eb531d94c81e407d721bf2962e0d The return type is the same, namely a Response with a status message. I can create a StatusSerializer with a charField of status. It would create an extra unnecessary abstraction.
Can you help me with this? class TeacherPermission(BasePermission):
def has_permission(self, request, view):
return request.user.is_teacher() How can I turn this into a thing Spectacular understands?
Thanks for the link to the tests. This is great:
No worries. Having this documentation is already better than nothing. |
I see no decorators here. The error message cannot happen like that. In any case, each serializer is baked into at least one component. Those live in the component section of the schema. For obvious reasons, collisions would be bad if they are referenced all over the schema. Each serializer needs a unique name (or unique name override) for this to work properly. If you use the same
great! you likely cannot do much more here.
This is outside the scope of simple auth methods. We can only distinguish between "auth required" or not and give details about the auth method (header, cookie, etc). OpenAPI is also limiting here. To get fine grained scopes, you would need to use OAuth, which OpenAPI explicitly supports (including scopes). |
closing this issue for now. feel free to comment if anything is missing or not working and we will follow-up. |
Hello, I've been converting more of our @api_views to use ClassBasedViews with serializers. It has been working out very well. Due to the templating tool used in the front-end we wrap list objects inside a dict. This is done with for the JSONrenderer and a with 'root' field on the serializer, i.e:
This is only done on responses, not requests. How can I go about achieving the wrapped objects in the API? |
Hey Roland
for a second there is thought this was a DRF feature I didn't know about. I can think of 2 solution.
|
Hi,
Indeed, that's my own add-on. Here's our code for the renderer.
Regarding 2, introducing a new mixin/base class. I tried that for one specific serializer to get the ball rolling. It didn't have the results I wanted:
What's the structure that should be returned? |
you must return a valid OpenAPI object, but we got helpers for that. this snippet should do what you want. class RootMixin:
pass
class YourSerializer(RootMixin, serializers.ModelSerializer):
class Meta:
model = M1
fields = '__all__'
root = 'foo'
from drf_spectacular.plumbing import build_object_type
class RootFix(OpenApiSerializerExtension):
target_class = 'path.to.RootMixin'
match_subclasses = True # !important for this
def map_serializer(self, auto_schema: 'AutoSchema', direction: Direction):
if direction == 'request':
return auto_schema._map_serializer(self.target, direction, bypass_extensions=True)
else:
schema = auto_schema._map_serializer(self.target, direction, bypass_extensions=True)
return build_object_type(
properties={self.target.Meta.root: schema}
)
|
1. Allows get_name with full parameters without breaking legacy code. 2. enable calling ``auto_schema.resolve_serializer`` with ``bypass_extensions=True`` to allow offloading component creation
my striken comment made me think about an old open issue. Have a look at this PR. It contains the second solution I was talking about. It just depends on those 2 new features, while above solution works right now. |
Thank you for quick the response, it's appreciated. 1 The proposed solution is getting me halfway there.
As a heads up, I don't know when I'll have more time to work on this part of our application. I hope it's soon. |
i missed that one. There is a way to handle this atm, but its gets a bit more tedious. set a custom
yeah that makes sense but only the response part, right?
sure, we can pick this up later. if this has no user interest, I just put it back on the pile. |
not sure what is the problem here, could you laborate? not using redoc that often myself. generally I look at the schema and see if the schema is as expected before concerning myself with the UI |
My understanding is as follows: Having a response that's different from the request results in two components. Example: Both POST and GET use the same component.
|
yes but not quite. This all hinges on the setting |
Thank you for your patience. Much appreciated. It works. The rabbit hole continues though. I also use the serializer as a readonly subserializer. Here the response isn't wrapped. |
Hi,
Thank you for creating and maintaining drf-spectacular. It's an awesome tool.
It's great that it's typed and it uses type hints to figure out.
I recently started using it and am encountering a couple rough edges. I'm using redoc for displaying the API.
Viewsets
The default is to use the first path of the url as the tag. The first part of my endpoints is /api/.
I had trouble figuring out what the default was.
What I expected was that one ViewSet, i.e. get, list, put, patch, post and delete, would be grouped together.
The same applies to the summary that's used to display. That it would have standard text for each generic part of the viewsets.
The DRF router already assigns names to these.
ApiView decorated functions
These functions themselves are relatively straightforward most of the time.
It seems there is a disconnect between the ease of use as a programmer and how to generate the documentation for them.
I haven't found a good way to handle these cases and the documentation is spares on how to handle it.
A couple examples: Multiple views have logic with custom responses. That is, variants on:
Response({"status": "invalid link" }, status=status.HTTP_400_BAD_REQUEST)
Specifying it with
@schema
results in:status: Encountered 2 components with identical names "status"
How to better handle these cases?
Another view returns important user data on login. To name a few: name, preferences, auth_groups, last_visted_page, company_name. I don't see good options for this view. extend_schema requires having the code twice, the same with creating a serializer. It would be alright to use a dataclass here, however, that needs to be wrapped inside a serializer to be picked up.
Is it possible to use a dataclass directly as the response?
Authorization
Is it possible to have permission classes show up in the schema?
Responses
How to show error responses for generic view sets? I.e. 400, BAD request, of 404 not found?
The text was updated successfully, but these errors were encountered: