I'd break my brain and loose/waste to much time to manage using Schema Decorator in DRF.
I follow https://www.django-rest-framework.org/topics/documenting-your-api/ and manage it but on sagger-ui and redoc-ui. But GET method query parameters or POST body json string payload aren't documented.
So i'm trying to deal with AutoSchema, ManualSchema and Custom classes to generate api documentation. https://www.django-rest-framework.org/api-guide/views/#view-schema-decorator
But i never manage anything good. and yes i looking through [django-rest-framework] tag on stackoverflow too and yes i open a discussion on DRF google community (but no answers yet).
So what i tried.
Try to deal:
import coreapi
import coreschema
from rest_framework.schemas import AutoSchema, ManualSchema
log_file_delete_schema = AutoSchema(
manual_fields=[
coreapi.Field(
"file_path",
required=True,
location="query",
type="string",
description="path of the log to be delete",
)
]
)
But it returns "AutoShema as no get_operation" error
Try next:
import coreapi
import coreschema
from rest_framework.schemas import AutoSchema, ManualSchema
class CustomLogFileDeleteSchema(AutoSchema):
def __init__(self):
super(CustomLogFileDeleteSchema, self).__init__
def get_manual_fields(self, path, method):
extra_fields = [
coreapi.Field(
"file_path",
required=True,
location="query",
description="log file path",
type="string",
example="/path/to/file/logfile.log",
)
]
manual_fields = super().get_manual_fields(path, method)
return manual_fields + extra_fields
It returns to me 'CustomLogFileDeleteSchema' object has no attribute 'instance_schemas'
I tried to use Django Rest Swagger but it's unmaintened project now so ==> next
I'm using function based views for non ORM api endpoint like this:
@api_view(["GET", "POST"])
# @schema(log_file_delete_schema)
#@schema(CustomLogFileDeleteSchema())
@permission_classes((permissions.AllowAny,))
def log_file_delete(request):
"""
@brief
Delete the current log file from the device
@param file_path => this is the log file path to delete
POST and GET requests only
e.g. uri looks like <root>/logs/delete/?file_path=/var/log/gpk/core.log
"""
api_logger.info("access to delete log view")
method = request.method
if "GET" == method:
_arg_file_path = request.GET.get("file_path", None)
if "POST" == method:
body_unicode = request.body.decode("utf-8")
body = json.loads(body_unicode)
_arg_file_path = body["file_path"]
if None is _arg_file_path or not _arg_file_path:
return JsonResponse({"error": "file_path arg is missing or empty"}, status=400)
try:
os.remove(Path(_arg_file_path))
open(_arg_file_path, "w") # need recreate empty file after delete
r = {"code": 202, "status_message": "job done! file deleted"}
except Exception as e:
r = {
"code": 400,
"status_message": "Ooops! there is an error when try to delete logs file %s, {}".format(
e
)
% _arg_file_path,
}
return JsonResponse(r, status=r["code"])
The View Schema Decorator example is too light for me, i don't understand what i can do with CustomClass Based on AutoSchema.
Please provide just a better example than inside the documentation about GET query and POST body payload doc in OpenAPI format to manage it un swagger-ui.
i've just opened an issue on github
After many hours to loose my time on github, stackoverflow, google, many dev blogs and forum i find a solution!
Thanks to this article i build OpenAPI dynamically follow docstring as yaml doc. https://www.igeorgiev.eu/python/misc/python-django-rest-framework-openapi-documentation/
So for my case, write yaml format docstring
# declare a subclass of
from rest_framework.schemas.openapi import AutoSchema
# not a subclass of
# from rest_framework.schemas import AutoSchema
# don't forget to import yaml from pyyaml package
import yaml
class AutoDocstringSchema(AutoSchema):
@property
def documentation(self):
if not hasattr(self, "_documentation"):
try:
self._documentation = yaml.safe_load(self.view.__doc__)
except yaml.scanner.ScannerError:
self._documentation = {}
return self._documentation
def get_components(self, path, method):
components = super().get_components(path, method)
doc_components = self.documentation.get("components", {})
components.update(doc_components)
return components
def get_operation(self, path, method):
operation = super().get_operation(path, method)
doc_operation = self.documentation.get(method.lower(), {})
operation.update(doc_operation)
return operation
@api_view(["GET", "POST"])
@permission_classes((permissions.AllowAny,))
@schema(AutoDocstringSchema())
def log_file_delete(request):
"""
get:
description: delete log file by using get method
summary: delete log file
parameters:
- name: file_path
in: query
description: file path of the log to delete
schema:
type: string
responses:
'200':
description: log file deleted
content:
'application/json': {}
"""
api_logger.info("access to delete log view")
method = request.method
if "GET" == method:
_arg_file_path = request.GET.get("file_path", None)
if "POST" == method:
body_unicode = request.body.decode("utf-8")
body = json.loads(body_unicode)
_arg_file_path = body["file_path"]
if None is _arg_file_path or not _arg_file_path:
return JsonResponse({"error": "file_path arg is missing or empty"}, status=400)
try:
os.remove(Path(_arg_file_path))
open(_arg_file_path, "w") # need recreate empty file after delete
r = {"code": 202, "status_message": "job done! file deleted"}
except Exception as e:
r = {
"code": 400,
"status_message": "Ooops! there is an error when try to delete logs file %s, {}".format(
e
)
% _arg_file_path,
}
return JsonResponse(r, status=r["code"])
NB: in this case i just wrote the yaml doc for the get method.
and then on swagger-ui get the parameter and everything we need
So i go to github DRF repository add this example and submit PR to update DRF documentation
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.