That’s the problem that Audoma is trying to solve, creating the most accurate documentation possible. Besides creating docs, Audoma also ensures that documentation is consistent with what’s defined in the code, trying to avoid situations where it differs from implemented functionality.
About Audoma
The main purpose of Audoma is to generate more accurate docs.
It has been built on the top of drf-spectacular, in fact extending many of its functionalities.
So, how does Audoma make life easier?
If you use drf-spectacular to add field example you’ll have to do this:
from drf_spectacular.utils import extend_schema_field
from rest_framework import fields
from rest_framework import serializers
@extend_schema_field(field={"example": random.randint(18, 150)})
class IntegerField(fields.IntegerField):
pass
@extend_schema_field(field={"example": "John"})
class NameField(fields.CharField):
pass
class PersonSerializer(serializers.Serializer):
name = fields.CharField(max_length=255)
age = IntegerField()
If you are using Audoma, you can simply do this:
from audoma.drf import serializers
class PersonSerializer(serializers.Serializer):
name = serializers.CharField(max_length=255, example="John")
age = serializers.IntegerField(min_value=18, max_value=150)
Setup
Audoma may be installed easily by using pip:
pip install audoma
After installation you have to modify your projects settings file:
REST_FRAMEWORK = {
# YOUR SETTINGS
'DEFAULT_SCHEMA_CLASS': 'audoma.drf.openapi.AudomaAutoSchema',
}
SCHEMA_PATTERN_PREFIX = 'api'
SPECTACULAR_SETTINGS = {
'PREPROCESSING_HOOKS':[
'audoma.hooks.preprocess_include_path_format'
],
# OTHER SETTINGS
}
That’s all, you can start using Audoma!
Example features
Audoma extends and automates many drf-spectacular behaviors.
As mentioned above, defining examples for fields in Audoma is much easier.
It also provides new fields that allow the definition of custom examples.
If you want to create a phone number field with example without Audoma this would require installing the proper package and then:
from django.db import models
from phonenumber_field.modelfields import PhoneNumberField
from drf_spectacular.utils import extend_schema_field
@extend_schema_field(field={
"example": "+123456789"
})
class CustomPhoneNumberField(PhoneNumberField):
pass
class Customer(models.Model):
name = models.CharField(max_length=255)
phone_number = CustomPhoneNumberField()
Audoma has this field built-in and provides two easy ways of defining examples:
from audoma.django import models
class Customer(models.Model):
name = models.CharField(max_length=255)
phone_number = models.PhoneNumberField(region="PL")
mobile_phone = models.PhoneNumberField(example="123456789")
If you pass example=”123456789″, the value would be shown as an example.
But if you pass region=”PL”, an example will be generated for the passed region, example will match the passed region phone number pattern.
Another great thing is that Audoma allows you to have multiple serializer classes defined on your Viewset:
from rest_framework.decorators import action
from rest_framework.response import Response
from audoma.drf import viewsets
from audoma.drf import mixins
from example_app.serializers import (
MyListSerializer,
MySerializer,
MyCreateSerializer
)
class MyViewSet(
mixins.ActionModelMixin,
mixins.ListModelMixin,
viewsets.GenericViewSet
):
serializer_class = MySerializer
get_new_action_result_serializer_class = MyListSerializer
post_new_action_result_serializer_class = MySerializer
post_new_action_collect_serializer_class = MyCreateSerializer
@action(detail=True, methods=["post", "get"])
def new_action(self, request, *args, **kwargs):
if request.method == "POST":
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exceptio n=True)
serializer.save()
instance = serializer.instance
else:
instance = self.get_object()
response_serializer = self.get_result_serializer(instance=instance)
return Response(response_serializer.data, status_code=201)
As you may see in the example above Audoma allows your Viewset action to have two different serializers for each served HTTP method. One for collecting data, the second for creating the response. With this on your Viewset you may also have the default serializer_class variable defined. To know more about audoma serializer class definitions see: Docs
More than that you may define those serializers per action using a custom action decorator!
class CarViewSet(
mixins.ActionModelMixin,
mixins.CreateModelMixin,
mixins.RetrieveModelMixin,
mixins.ListModelMixin,
viewsets.GenericViewSet,
):
@audoma_action(
detail=False,
methods=["get", "post"]
collectors=CarCreateRateSerializer,
results={
"post":{201: CarRateSerializer},
"get":{200: CarDetailsSerializer}
},
errors=[CustomCarException]
)
def rate(self, request, *args, **kwargs):
if settings.RATE_AVAILABLE:
return None, 204
if request.method == "POST":
collect_serializer = kwargs.pop("collect_serializer")
instance = collect_serializer.save()
return instance. 201
else:
instance = car.objects.get(pk=pk)
if not instance:
raise CustomCarException
return instance, 200
Using this action you may define different serializers for data collection and response generation.
What’s great is that all of the serializers defined in audoma_action will be documented properly.
If you want to learn more about audoma, please visit our repo, or simply read the documentation.
Contribution
Audoma accepts any type of contribution to the project!
All new feature or fix proposals should be created via pull request or issue in our repository.
Pull requests
We advise sticking to the below rules:
Test your changes before creating pull requests – your code has to pass the whole test suite to get merged. The best way will be by launching docker tests, included with the project
Use linters included in Audoma
Write your own tests for your changes
If your changes are not trivial consider creating an issue first with changes proposals to get some early feedback
If you are introducing a new feature, please add an example for this feature in Audoma example application
Issues
To each submitted issue, please include:
Brief description of the issue
Stack trace if there has been an exception raised
Code that caused the issue
audoma/drf-spectacular/Django/DRF versions