Usage
Viewset defined serializers
class MyViewSet(viewsets.ModelViewSet):
serializer_class = MySerializer
collect_serializer_class = MyCollectSerializer
result_serializer_class = MyResultSerializer
class MyViewSet(viewsets.ModelViewSet):
create_serializer_class = MyCreateSerializer
class MyViewSet(viewsets.ModelViewSet):
get_list_serializer_class = MyListSerializer
post_list_serializer_class = MyBulkCreateSerializer
class MyViewSet(viewsets.ModelViewSet):
create_collect_serializer = MyModelCreateSerializer
create_result_serializer = MyModelSerializer
class MyViewSet(viewsets.ModelViewSet):
get_list_serializer_class = MyListSerializer
post_list_serializer_class = MyBulkCreateSerializer
class MyViewSet(viewsets.ModelViewSet):
serializer_class = MySerializer
collect_serializer_class = MyCollectSerializer
result_serializer_class = MyResultSerializer
create_serializer_class = MyCreateSerializer
get_list_serializer_class = MyListSerializerfeatures
{method}_{action}_{type}_serializer_class
{action}_{type}_serializer_class
{method}_{action}_serializer_class
{action}_serializer_class
common_{type}_serializer_class
serializer_class
Permissions
By default, in the drf-spectacular viewset permissions were not documented at all. Currently, permissions are being documented for each viewset separately.
You don’t have to define anything extra, this is being handled just out of the box. The only thing it is required is to define permissions on your viewset.
Example:
class ExampleModelViewSet(
mixins.ActionModelMixin,
mixins.CreateModelMixin,
mixins.RetrieveModelMixin,
mixins.DestroyModelMixin,
mixins.ListModelMixin,
viewsets.GenericViewSet,
):
permission_classes = [
IsAuthenticated,
ViewAndDetailPermission,
DetailPermission,
ViewPermission,
AlternatePermission1 | AlternatePermission2,
]
...
Custom choices
Example:
if body_type == BODY_TYPE_CHOICES.SEDAN:
...
To create custom choices you have to use the make_choices method.
from audoma.choices import make_choices
...
class ExampleModel(models.Model):
EXAMPLE_CHOICES = make_choices(
"CHOICES",
(
(1, "EX_1", "example 1"),
(2, "EX_2", "example 2"),
(3, "EX_3", "example 3"),
),
)
....
choices = models.IntegerField(choices=EXAMPLE_CHOICES.get_choices())
Filters
Default Filters
class CarViewSet(
mixins.ActionModelMixin,
mixins.RetrieveModelMixin,
mixins.ListModelMixin,
viewsets.GenericViewSet,
):
queryset = Car.objects.none()
serializer_class = CarModelSerializer
filter_backends = [SearchFilter, df_filters.DjangoFilterBackend]
filterset_fields = ["engine_type"]
search_fields = ["=manufacturer", "name"]
Validators
ExclusiveFieldsValidator
fields - list or a tuple of field names
message - string message, which will replace default validator message
required - boolean which determines if any of the fields must be given
- message_required - a message which will be displayed if one of the fields is required,
and none has been passed
class MutuallyExclusiveExampleSerializer(serializers.Serializer):
class Meta:
validators = [
ExclusiveFieldsValidator(
fields=[
"example_field",
"second_example_field",
]
),
]
example_field = serializers.CharField(required=False)
second_example_field = serializers.CharField(required=False)
Decorators
@extend_schema_field
from audoma.drf.fields import FloatField
from drf_spectacular.utils import extend_schema_field
@extend_schema_field(
field={
"example": 10.00
}
)
class CustomExampleFloatField(FloatField):
...
@audoma_action
collectors
@audoma_action(
detail=False,
methods=["post"],
results=ExampleOneFieldSerializer,
collectors=ExampleOneFieldSerializer,
)
@audoma_action(
detail=True,
methods=["post"],
collectors={"post": ExampleModelCreateSerializer},
results={
"post": {201: ExampleModelSerializer, 202: ExampleOneFieldSerializer}
},
)
def detail_action(self, request, collect_serializer, pk=None):
...
@audoma_action(
detail=True,
methods=["post", "patch"],
collectors={
"post": ExampleModelCreateSerializer,
"patch": ExampleModelUpdateSerializer
},
results={
"post": {
201: ExampleModelSerializer,
202: ExampleOneFieldSerializer
},
"patch": {
200: ExampleModelSerializer,
202: ExampleOneFieldSerializer
}
},
)
def detail_action(self, request, collect_serializer, pk=None):
...
Important
results
@audoma_action(
detail=True,
methods=["put", "patch"],
collectors=ExampleModelCreateSerializer,
results=ExampleModelSerializer,
)
def example_update_action(self, request, collect_serializer, pk=None):
...
@audoma_action(
detail=True,
methods=["post"],
collectors={"post": ExampleModelCreateSerializer},
results={"post": {201: ExampleModelSerializer, 202: ExampleOneFieldSerializer}},
)
def detail_action(self, request, collect_serializer, pk=None):
...
@audoma_action(
detail=False,
methods=["get"],
results={"get": {200: "This is a test view", 404: "Not found"}},
)
def non_detail_action(self, request):
...
errors
NotFound
NotAuthenticated
AuthenticationFailed
ParseError
PermissionDenied
COMMON_API_ERRORS = [
myexceptions.SomeException
]
ignore_view_collectors
Examples
Define example for field
class ExampleSerializer(serializers.Serializer):
...
phone_number_example = serializers.PhoneNumberField(example="+48 123 456 789")
...
Define custom fields with auto-generated examples
from rest_framework import fields
from audoma.mixins import ExampleMixin
from audoma.examples import NumericExample,
class SomeExampleField(ExampleMixin, fields.Field):
audoma_example_class = NumericExample
Define custom example classes
NumericExample
RegexExample
And one general class: * Example
from audoma.examples import Example
class MyExample(Example):
def generate_value(self):
return "My example value"
Extra Fields
Money Field
from audoma.django.db import models
class ExamplePerson(models.Model):
...
savings = models.MoneyField(max_digits=14, decimal_places=2, default_currency="PLN")
...
PhoneNumberField
Audoma provides a PhoneNumberField which is an extension of the django-phonenumber-field. You can use it in your models straight away, just as the original PhoneNumberField, and what we added here is an automatically generated example in documentation, based on country code.
Example:
from audoma.django.db import models
class ExamplePerson(models.Model):
...
phone_number = models.PhoneNumberField(region="GB")
...
Above will result in the following example in the documentation:
{
...
"phone_number": "+44 20 7894 5678",
...
}
Serializer Field links
class CarModelSerializer(serializers.ModelSerializer):
choices_options_links = {
"manufacturer": {
"viewname": "manufacturer_viewset-list",
"value_field": "id",
"display_field": "name",
}
}
manufacturer = serializers.IntegerField()
class Meta:
model = Car
fields = "__all__"
viewname - the name of a view from which variables should be retrieved
value_field - field name from which value should be retrieved
display_field - field name from which display value should be retrieved
Schema Extensions
x-choices
{
"x-choices": {
"choices": {
"value1": "displayValue1",
"value2": "displayValue2",
"value3": "displayValue3",
"value4": "displayValue4",
}
}
}
{
"x-choices": {
"operationRef": "#/paths/manufacturer_viewset~1",
"value": "$response.body#results/*/id",
"display": "$response.body#results/*/name"
}
}