Closed Wissperwind closed 2 years ago
Is it possible to type in directly the text that is displayed in the results field? I think it would be mouch easier than writing serializers. Also I miss the option to specify the content of my result:
"results": {
"additionalProp1": "string",
"additionalProp2": "string",
"additionalProp3": "string"
}
Ok, the result is some kind of dict. But I would like to tell the user that the keys in that result dict are "pdf", "xml", and "csv".
This results in:
This does not look like something spectacular generates
(200, 'application/json'): is a key in a dict. So I can not descibe different 200 answers.
You can't by design. You can however use PolymorphicProxySerializer
, which lets you model OR requests/responses.
The errors parameter in reality is a list of strings. So ["error 1", "error 2"] How can I specify this?
There is likely a way to model this with PolymorphicProxySerializer
and inline_serializer
but you are kind of doing something unusual which might make it cumbersome. The easiest way to do would be by raw schema. This is usually a last resort but might be warranted here
from drf_spectacular.plumbing import build_array_type, build_basic_type
from drf_spectacular.types import OpenApiTypes
@extend_schema(
responses={
(200, 'application/json'): {
'oneOf': [
build_array_type(build_basic_type(str)),
build_basic_type(OpenApiTypes.OBJECT) # or build_basic_type(dict)
]
}
},
)
How can I add explanative text about the response of the view?
@extend_schema(summary="foo", description="bar" responses=...)
This would be nice. So the endpoint does it's thing, and it gives a 200 because the request was correct and so on. But there are two cases. The case where it worked, and the case where something went wrong.
responses={
(200, 'application/json'): {
'oneOf': [
inline_serializer(
"Result",
fields={
"results": JSONField()
},
),
inline_serializer(
"Error",
fields={
"errors": GeneralErrorSerializer(),
}
)
]
}
},
What makes you think the "this results in" part in the first post was nothing generated by drf-spectacular? Of course it was. It was directly copied from the response section of the swagger page.
What makes you think the "this results in" part in the first post was nothing generated by drf-spectacular?
nevermind. you showed the example output of swagger-ui, which was not immediately clear to me. In the schema it looks a bit different: "additionalProperties": {},
Regarding your example. That does not work as you either do a raw schema or let spectacular process serializers. Can't do both. However, you you could use PolymorphicProxySerializer
instead of the oneOf
dict which is again valid.
PolymorphicProxySerializer(
component_name='SomeName',
serializers=[inline_serializer(...), inline_serializer(...)],
resource_type_field_name=None,
)
Apart from that, the ErrorSerializer
would be wrong as it returns a object which is not what I understood what you need.
your version: {"errors": ["error1", "error1"]}
my version: ["error1", "error1"]
Also consider dropping (200, 'application/json'):
for 200:
as it might already be discovered correctly.
Ok. I tried:
responses={
200:
PolymorphicProxySerializer(
component_name='SomeName',
serializers=[
inline_serializer(
"Result",
fields={
"results": JSONField()
},
),
inline_serializer(
"Error",
fields={
"errors": GeneralErrorSerializer(),
},
),
],
resource_type_field_name=None,
)
},
In Swagger that just looks like:
{
"results": {
"additionalProp1": "string",
"additionalProp2": "string",
"additionalProp3": "string"
}
}
Maybe I am on the wrong path. What is the best practise to build and document an enpoint that could give some errors or some results?
so you are misleading yourself. swagger-ui will only show the example for the first oneOf
item. that is a design choice by swagger-ui. If you want to understand whats going on I urge to to also look into the schema as a sanity check. swagger-ui sometimes makes unexpected choices. It will however show up in the Schema
tab.
If you want to make those examples more prominent, you will need to add explicit manual examples with OpenApiExample
. Then there will be a dropdown directly visible in the "value" tab.
for error handling it is more RESTy if you do
@extend_schema(responses={
200: RegularSerializer,
400: ErrorSerializer,
"4XX": GenericErrorSerializer,
})
it is bad practice to give 200 on errors. imho that is why you struggle to model this properly. OpenAPI will make it difficult if you go against the grain.
Ah, it is recommended to respond with 400 Bad Request, even if the request syntax was correct but for example some data is missing. I will do that. Thanks! I am now at that state:
I would wish for something like that:
Of course withou the red lines. That was just my german powerpoint.
2 choices.
inline_serializer
to flesh out xml
etc. inline_serializer(..., fields={results: inline_serializer(...)})
@extend_schema(
responses={
200: RegularSerializer,
400: ErrorSerializer,
"4XX": GenericErrorSerializer,
},
examples=[
OpenApiExample(
'Example name',
summary="some text",
value={'xml': 'link to xml file', 'pdf': 'link to pdf file', },
# response_only=True, # only needed for POST
# status_codes=[..] # not needed for 200,201
)
]
)
there are many ways to provide examples. this is just one way. can also be attached to serializer or wrapped in responses with OpenApiResponse()
Ah, I have not noticed on read the docs that there is a "general" example section, that makes examples for the response. I was just focused on the examples for the parameter. I think I can describe my results now. Thanks!
I have a custom view. It does not respond something created by a django serializer. At the moment I described it like this:
This results in:
But this is not how my endpoint works. You get either a list of errors or a dict of results. But in both cases I thought the code 200 would be correct, because the server did it's thing. The following problems: