Sane and flexible OpenAPI 3 schema generation for Django REST framework.

Overview

drf-spectacular

build-status-image codecov pypi-version docs

Sane and flexible OpenAPI 3.0 schema generation for Django REST framework.

This project has 3 goals:
  1. Extract as much schema information from DRF as possible.
  2. Provide flexibility to make the schema usable in the real world (not only toy examples).
  3. Generate a schema that works well with the most popular client generators.

The code is a heavily modified fork of the DRF OpenAPI generator, which is/was lacking all of the below listed features.

Features
  • Serializers modelled as components. (arbitrary nesting and recursion supported)
  • @extend_schema decorator for customization of APIView, Viewsets, function-based views, and @action
    • additional parameters
    • request/response serializer override (with status codes)
    • polymorphic responses either manually with PolymorphicProxySerializer helper or via rest_polymorphic's PolymorphicSerializer)
    • ... and more customization options
  • Authentication support (DRF natives included, easily extendable)
  • Custom serializer class support (easily extendable)
  • SerializerMethodField() type via type hinting or @extend_schema_field
  • i18n support
  • Tags extraction
  • Request/response/parameter examples
  • Description extraction from docstrings
  • Sane fallbacks
  • Sane operation_id naming (based on path)
  • Schema serving with SpectacularAPIView (Redoc and Swagger-UI views are also available)
  • Optional input/output serializer component split
  • Included support for:

For more information visit the documentation.

License

Provided by T. Franzel, Cashlink Technologies GmbH. Licensed under 3-Clause BSD.

Requirements

  • Python >= 3.6
  • Django (2.2, 3.1, 3.2)
  • Django REST Framework (3.10, 3.11, 3.12)

Installation

Install using pip...

$ pip install drf-spectacular

then add drf-spectacular to installed apps in settings.py

INSTALLED_APPS = [
    # ALL YOUR APPS
    'drf_spectacular',
]

and finally register our spectacular AutoSchema with DRF.

REST_FRAMEWORK = {
    # YOUR SETTINGS
    'DEFAULT_SCHEMA_CLASS': 'drf_spectacular.openapi.AutoSchema',
}

drf-spectacular ships with sane default settings that should work reasonably well out of the box. It is not necessary to specify any settings, but we recommend to specify at least some metadata.

SPECTACULAR_SETTINGS = {
    'TITLE': 'Your Project API',
    'DESCRIPTION': 'Your project description',
    'VERSION': '1.0.0',
    # OTHER SETTINGS
}

Release management

drf-spectacular deliberately stays below version 1.x.x to signal that every new version may potentially break you. For production we strongly recommend pinning the version and inspecting a schema diff on update.

With that said, we aim to be extremely defensive w.r.t. breaking API changes. However, we also acknowledge the fact that even slight schema changes may break your toolchain, as any existing bug may somehow also be used as a feature.

We define version increments with the following semantics. y-stream increments may contain potentially breaking changes to both API and schema. z-stream increments will never break the API and may only contain schema changes that should have a low chance of breaking you.

Take it for a spin

Generate your schema with the CLI:

$ ./manage.py spectacular --file schema.yml
$ docker run -p 80:8080 -e SWAGGER_JSON=/schema.yml -v ${PWD}/schema.yml:/schema.yml swaggerapi/swagger-ui

If you also want to validate your schema add the --validate flag. Or serve your schema directly from your API. We also provide convenience wrappers for swagger-ui or redoc.

from drf_spectacular.views import SpectacularAPIView, SpectacularRedocView, SpectacularSwaggerView
urlpatterns = [
    # YOUR PATTERNS
    path('api/schema/', SpectacularAPIView.as_view(), name='schema'),
    # Optional UI:
    path('api/schema/swagger-ui/', SpectacularSwaggerView.as_view(url_name='schema'), name='swagger-ui'),
    path('api/schema/redoc/', SpectacularRedocView.as_view(url_name='schema'), name='redoc'),
]

Usage

drf-spectacular works pretty well out of the box. You might also want to set some metadata for your API. Just create a SPECTACULAR_SETTINGS dictionary in your settings.py and override the defaults. Have a look at the available settings.

The toy examples do not cover your cases? No problem, you can heavily customize how your schema will be rendered.

Customization by using @extend_schema

Most customization cases should be covered by the extend_schema decorator. We usually get pretty far with specifying OpenApiParameter and splitting request/response serializers, but the sky is the limit.

from drf_spectacular.utils import extend_schema, OpenApiParameter, OpenApiExample
from drf_spectacular.types import OpenApiTypes

class AlbumViewset(viewset.ModelViewset)
    serializer_class = AlbumSerializer

    @extend_schema(
        request=AlbumCreationSerializer
        responses={201: AlbumSerializer},
    )
    def create(self, request):
        # your non-standard behaviour
        return super().create(request)

    @extend_schema(
        # extra parameters added to the schema
        parameters=[
            OpenApiParameter(name='artist', description='Filter by artist', required=False, type=str),
            OpenApiParameter(
                name='release',
                type=OpenApiTypes.DATE,
                location=OpenApiParameter.QUERY,
                description='Filter by release date',
                examples=[
                    OpenApiExample(
                        'Example 1',
                        summary='short optional summary',
                        description='longer description',
                        value='1993-08-23'
                    ),
                    ...
                ],
            ),
        ],
        # override default docstring extraction
        description='More descriptive text',
        # provide Authentication class that deviates from the views default
        auth=None,
        # change the auto-generated operation name
        operation_id=None,
        # or even completely override what AutoSchema would generate. Provide raw Open API spec as Dict.
        operation=None,
        # attach request/response examples to the operation.
        examples=[
            OpenApiExample(
                'Example 1',
                description='longer description',
                value=...
            ),
            ...
        ],
    )
    def list(self, request):
        # your non-standard behaviour
        return super().list(request)

    @extend_schema(
        request=AlbumLikeSerializer
        responses={204: None},
        methods=["POST"]
    )
    @extend_schema(description='Override a specific method', methods=["GET"])
    @action(detail=True, methods=['post', 'get'])
    def set_password(self, request, pk=None):
        # your action behaviour

More customization

Still not satisifed? You want more! We still got you covered. Visit customization for more information.

Testing

Install testing requirements.

$ pip install -r requirements.txt

Run with runtests.

$ ./runtests.py

You can also use the excellent tox testing tool to run the tests against all supported versions of Python and Django. Install tox globally, and then simply run:

$ tox
Comments
  • AssertionError Serializer

    AssertionError Serializer

    i have an serializer who give me an exception, follow my traceback:

    File "./manage.py", line 17, in <module>
        execute_from_command_line(sys.argv)
      File "/usr/local/lib/python3.7/site-packages/django/core/management/__init__.py", line
    381, in execute_from_command_line
        utility.execute()
      File "/usr/local/lib/python3.7/site-packages/django/core/management/__init__.py", line
    375, in execute
        self.fetch_command(subcommand).run_from_argv(self.argv)
      File "/usr/local/lib/python3.7/site-packages/django/core/management/base.py", line 323,
     in run_from_argv
        self.execute(*args, **cmd_options)
      File "/usr/local/lib/python3.7/site-packages/django/core/management/base.py", line 364,
     in execute
        output = self.handle(*args, **options)
      File "/usr/local/lib/python3.7/site-packages/drf_spectacular/management/commands/specta
    cular.py", line 44, in handle
        schema = generator.get_schema(request=None, public=True)
      File "/usr/local/lib/python3.7/site-packages/drf_spectacular/generators.py", line 161,
    in get_schema
        paths=self.parse(request, public),
      File "/usr/local/lib/python3.7/site-packages/drf_spectacular/generators.py", line 141,
    in parse
        operation = view.schema.get_operation(path, path_regex, method, self.registry)
      File "/usr/local/lib/python3.7/site-packages/drf_spectacular/openapi.py", line 77, in g
    et_operation
        operation['responses'] = self._get_response_bodies()
      File "/usr/local/lib/python3.7/site-packages/drf_spectacular/openapi.py", line 822, in
    _get_response_bodies
        return {'200': self._get_response_for_code(response_serializers)}
      File "/usr/local/lib/python3.7/site-packages/drf_spectacular/openapi.py", line 847, in
    _get_response_for_code
        component = self.resolve_serializer(serializer, 'response')
      File "/usr/local/lib/python3.7/site-packages/drf_spectacular/openapi.py", line 919, in
    resolve_serializer
        component.schema = self._map_serializer(serializer, direction)
      File "/usr/local/lib/python3.7/site-packages/drf_spectacular/openapi.py", line 580, in
    _map_serializer
        schema = self._map_basic_serializer(serializer, direction)
      File "/usr/local/lib/python3.7/site-packages/drf_spectacular/openapi.py", line 639, in
    _map_basic_serializer
        schema = self._map_serializer_field(field, direction)
      File "/usr/local/lib/python3.7/site-packages/drf_spectacular/openapi.py", line 398, in
    _map_serializer_field
        component = self.resolve_serializer(field, direction)
      File "/usr/local/lib/python3.7/site-packages/drf_spectacular/openapi.py", line 919, in
    resolve_serializer
        component.schema = self._map_serializer(serializer, direction)
      File "/usr/local/lib/python3.7/site-packages/drf_spectacular/openapi.py", line 580, in
    _map_serializer
        schema = self._map_basic_serializer(serializer, direction)
      File "/usr/local/lib/python3.7/site-packages/drf_spectacular/openapi.py", line 639, in
    _map_basic_serializer
        schema = self._map_serializer_field(field, direction)
      File "/usr/local/lib/python3.7/site-packages/drf_spectacular/openapi.py", line 403, in
    _map_serializer_field
        component = self.resolve_serializer(field.child, direction)
      File "/usr/local/lib/python3.7/site-packages/drf_spectacular/openapi.py", line 919, in
    resolve_serializer
        component.schema = self._map_serializer(serializer, direction)
      File "/usr/local/lib/python3.7/site-packages/drf_spectacular/openapi.py", line 580, in
    _map_serializer
        schema = self._map_basic_serializer(serializer, direction)
      File "/usr/local/lib/python3.7/site-packages/drf_spectacular/openapi.py", line 639, in
    _map_basic_serializer
        schema = self._map_serializer_field(field, direction)
      File "/usr/local/lib/python3.7/site-packages/drf_spectacular/openapi.py", line 403, in
    _map_serializer_field
        component = self.resolve_serializer(field.child, direction)
      File "/usr/local/lib/python3.7/site-packages/drf_spectacular/openapi.py", line 919, in
    resolve_serializer
        component.schema = self._map_serializer(serializer, direction)
      File "/usr/local/lib/python3.7/site-packages/drf_spectacular/openapi.py", line 580, in
    _map_serializer
        schema = self._map_basic_serializer(serializer, direction)
      File "/usr/local/lib/python3.7/site-packages/drf_spectacular/openapi.py", line 639, in
    _map_basic_serializer
        schema = self._map_serializer_field(field, direction)
      File "/usr/local/lib/python3.7/site-packages/drf_spectacular/openapi.py", line 398, in
    _map_serializer_field
        component = self.resolve_serializer(field, direction)
      File "/usr/local/lib/python3.7/site-packages/drf_spectacular/openapi.py", line 919, in
    resolve_serializer
        component.schema = self._map_serializer(serializer, direction)
      File "/usr/local/lib/python3.7/site-packages/drf_spectacular/openapi.py", line 580, in
    _map_serializer
        schema = self._map_basic_serializer(serializer, direction)
      File "/usr/local/lib/python3.7/site-packages/drf_spectacular/openapi.py", line 639, in
    _map_basic_serializer
        schema = self._map_serializer_field(field, direction)
      File "/usr/local/lib/python3.7/site-packages/drf_spectacular/openapi.py", line 403, in
    _map_serializer_field
        component = self.resolve_serializer(field.child, direction)
      File "/usr/local/lib/python3.7/site-packages/drf_spectacular/openapi.py", line 919, in
    resolve_serializer
        component.schema = self._map_serializer(serializer, direction)
      File "/usr/local/lib/python3.7/site-packages/drf_spectacular/openapi.py", line 580, in
    _map_serializer
        schema = self._map_basic_serializer(serializer, direction)
      File "/usr/local/lib/python3.7/site-packages/drf_spectacular/openapi.py", line 639, in
    _map_basic_serializer
        schema = self._map_serializer_field(field, direction)
      File "/usr/local/lib/python3.7/site-packages/drf_spectacular/openapi.py", line 403, in
    _map_serializer_field
        component = self.resolve_serializer(field.child, direction)
      File "/usr/local/lib/python3.7/site-packages/drf_spectacular/openapi.py", line 907, in
    resolve_serializer
        assert is_serializer(serializer)
    AssertionError
    
    
    bug 
    opened by danilocastelhano1 21
  • django-rest-framework-gis

    django-rest-framework-gis

    https://github.com/openwisp/django-rest-framework-gis causes warning

    could not resolve serializer field GeometryField(allow_null=True, required=False). defaulting to "string"

    It definitely isnt a string ;-)

    enhancement help wanted fix confirmation pending 
    opened by jayvdb 21
  • Support for different API versions

    Support for different API versions

    There are different versions of API in my current project. Like ​/api​/v{version}​/... Is it possible to give different serializers depending on the version of api? I saw a similar implementation in the framework fastapi-versioning

    Is there any possible solution to this problem? I will be very grateful for your advice

    enhancement 
    opened by MissiaL 20
  • drf-spectacular does not detect any schema

    drf-spectacular does not detect any schema

    Hello,

    I am trying to generate an open Api documentation using your library, however I keep getting the No operations defined in spec! while using the ui. I believe it is an error due to my own implementation.

    All my view can be find like this:

    my app / views / view1.py view2.py

    I mostly use the generics views, here is an example:

    class SystemDetail(generics.RetrieveAPIView):
    """ Get a system detail
    User in group x can see all system.
    Other groups have access to system with the corresponding dealer name.
    
    For now it return Not Found id Not Authorized.
    """
    
    lookup_field = 'uuid'
    
    def get_queryset(self):
        user_groups = self.request.user.groups.all().values_list('name', flat=True)
    
        if 'x' not in user_groups:
            dealer = MANUFACTER_CHOICE
            dealer_name: str = [dealer_name[1] for dealer_name in dealer if dealer_name[1].lower() in user_groups][0]
            return System.objects.filter(dealer__name=dealer_name)
        return System.objects.all()
    
    def get_serializer_class(self):
        user_groups = self.request.user.groups.all().values_list('name', flat=True)
    
        if 'x' not in user_groups:
            return ExternalSystemSerializer
        return SystemSerializer
    

    I set up drf-spectacular using the docs. I added it to my INSTALLED_APPS in my settings.py and in my urls.

    urlpatterns = [
    # back
    path('', include('api.urls')),
    path('schema/', SpectacularAPIView.as_view(), name='schema'),
    # Optional UI:
    path('schema/swagger-ui/', SpectacularSwaggerView.as_view(url_name='schema'), name='swagger-ui'),
    path('schema/redoc/', SpectacularRedocView.as_view(url_name='schema'), name='redoc'),
    path('v1/', include('users.urls.v1', namespace='users')),]
    

    All my endpoint are served under my-domain-name/v1/my-endpoint.

    When I try to see my swagger It returns an empty dict as if I had no views in my project, however when I was using drf-yasg I could see all my endopints.

    I tried to add this to my settings.py, same result.

    SPECTACULAR_SETTINGS = { "SCHEMA_PATH_PREFIX": "/v1" }

    Where Am I doing wrong ?

    Thank you

    opened by RomikimoR 19
  • Default django-filter types and overriding types

    Default django-filter types and overriding types

    There's a long-standing issue in django-filter, where the typing of parameters ends up wrong in the resulting OpenAPI schema, due to them being hardcoded as 'string' in django-filter: https://github.com/carltongibson/django-filter/blob/6045fff/django_filters/rest_framework/backends.py#L164

    This is the closest related GitHub issue that I am aware of https://github.com/carltongibson/django-filter/issues/1104

    Is it at this point possible to resolve this using drf-spectacular, and I just have not figured out how?

    If not, then would it be plausible to add to drf-spectacular's contrib.django_filters something similar to this https://github.com/tfranzel/drf-spectacular/blob/master/drf_spectacular/openapi.py#L396 that would check if the parameters are instances of specific django-filter filters, such as filters.NumberFilter -> would map to some numeric type?

    If that is too far-fetched as well, then is it possible to override only the parameter type using drf-spectacular? It would seem that if I override the parameter with OpenApiParameter then it replaces the whole schema for the parameter.

    Or if none of these are anywhere near the solution, what would you suggest for solving the wrong typing, or what approach have you or others used? The library includes some support for django-filter so it does not seem to be a completely new use case.

    bug fix confirmation pending 
    opened by indigane 19
  • Documentation for Authentication

    Documentation for Authentication

    I am attempting to set up drf-spectacular and am struggling to configure authentication.

    We have extended DRF's TokenAuthentication, and it is included in the authentication_classes list on the target APIView. We also have another custom authentication class, which does not match any AuthenticationExtensions.

    If authentication_classes=[SubclassedTokenAuthentication] only (excluding our other authentication), then the "Authorize" button appears in Swagger. When we add the other authentication class, no "Authorize" button appears in Swagger.

    Ideally, if any of the list of authentication_classes matches one of the AuthenticationExtensions, then that should be used in the resulting schema. Alternatively, being able to configure via the extend_schema(auth=?) kwarg would work - but I cannot find documentation for this argument.

    Thanks for the great library!

    opened by savitmk 18
  • Wrong django-filter types

    Wrong django-filter types

    django-filter fields can have a different type from the underlying model field they operate against. drf-spectacular incorrectly makes the schema type match the model field instead of the filter.

    Take the following filter for example:

    class UserFilter(django_filters.FilterSet):
        has_logged_in = django_filters.BooleanFilter(field_name='last_login', lookup_expr='isnull')
    

    last_login is a datetime model field but the filter field is boolean. Currently the schema has the type for has_logged_in as datetime which is incorrect.

    The reason, I believe, is this part of the code: https://github.com/tfranzel/drf-spectacular/blob/243445f719e574ef8b292428070f93d62e647ddd/drf_spectacular/contrib/django_filters.py#L57-L60

    The model field type is preferred over the actual filter type.

    I don't understand why the model field is even used here. Is it to get additional information? Since the filter itself has a clear type I don't think the mode field type is ever relevant.

    bug fix confirmation pending 
    opened by markopy 17
  • function based views @api_view and request.POST (form based) parameters

    function based views @api_view and request.POST (form based) parameters

    I am going through a migration process from 1.11 to 3.1.5. And I found out drf-spectacular may provide a way to do this API migration.

    I'ved got the question posted here in detail: https://stackoverflow.com/questions/65918969/django-rest-framework-custom-post-url-endpoints-with-defined-parameter-request?noredirect=1#comment116622930_65918969

    Basically, I'd like to find a way to create REST API using drf-spectacular that is equivalent to this:

    url.py url(r'^api/test_token$', api.test_token, name='test_token'),

    api.py

    @api_view(['POST'])
    def test_token(request):
        # ----- YAML below for Swagger -----
        """
        description: test_token
        parameters:
          - name: token
            type: string
            required: true
            location: form       
        """
        token = request.POST['token']
    
        return Response("test_token success", status=status.HTTP_200_OK)
    

    In the documentation, there is mentioned how to handle @api_view https://drf-spectacular.readthedocs.io/en/latest/customization.html#

    Many libraries use @api_view or APIView instead of ViewSet or GenericAPIView. In those cases, introspection has very little to work with. The purpose of this extension is to augment or switch out the encountered view (only for schema generation). Simply extending the discovered class class Fixed(self.target_class) with a queryset or serializer_class attribute will often solve most issues.

    I am not sure how its done, could someone give some guidance how to get this to work ? Thanks.

    fix confirmation pending 
    opened by axilaris 17
  • Specify JSON Schema for JSONFields

    Specify JSON Schema for JSONFields

    I have a few JSON Fields specified on one of my models. I have defined JSON Schemas for those fields, which I use to validate the data. I'd like to include those JSON Schemas on the OpenAPI schema generated by drf-spectacular. I know that it is possible to convert the JSON Schema to OpenAPI, but I was unable to find a way to do it with drf-spectacular. Is this supported somehow?

    opened by mateokurti 16
  • Using DRF spectacular

    Using DRF spectacular

    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?

    opened by rvanlaar 16
  • Getting working drf-spectacular package for Debian 11 stable

    Getting working drf-spectacular package for Debian 11 stable

    Hello,

    I'm sorry to bother you with such issue, as I guessed, it's occurring on my side but I fails to understand what's going on here... It used to works just fine with 0.11.1 but fails with 0.13.1. I did not try with newer version because I did not find anything related in changelog. Why is failing when trying to import this module if I'm not using it ?

    Thanks a lot in advance,

    Best regards, Adam. traceback.txt

    opened by eLvErDe 15
  • Custom Versioning support in DRF Swagger doesn't work

    Custom Versioning support in DRF Swagger doesn't work

    For versioning in my code, I was planning to use AcceptHeaderVersioning in DRF but got into a roadblock as described in this issue.

    The option left for me would be using CustomVersioning with a new header sent for every request. I added DEFAULT_VERSIONING_CLASS to be the custom versioning. But, I see that DRF-spectacular swagger produces a warning - "Warning: using unsupported versioning class" and swagger points to page saying "No operations defined in spec!"

    What I am looking for is to set a common custom version header in the request for all APIs in the swagger which can be set globally in the swagger top bar(Similar to authorizations button) and server reads the header in the middleware to take actions. Can we do that?

    opened by johnugeorge 0
  • How to automatically render schema fields?

    How to automatically render schema fields?

    Is there a setting that will automatically display field data?

    Settings:

    SPECTACULAR_SETTINGS = {
        'SERVE_INCLUDE_SCHEMA': False,
        # Permission
        'SERVE_AUTHENTICATION': ['rest_framework.authentication.SessionAuthentication'],
        'SERVE_PERMISSIONS': ['rest_framework.permissions.IsAuthenticated'],
        # UI settings
        'SWAGGER_UI_DIST': 'SIDECAR',  # shorthand to use the sidecar instead
        'SWAGGER_UI_FAVICON_HREF': 'SIDECAR',
        'REDOC_DIST': 'SIDECAR',
        'SCHEMA_PATH_PREFIX_TRIM': True,
    }
    

    In the swagger, the data is reflected in this form:

    Screenshot 2022-12-28 at 08 49 16

    Is it possible to automatically expand the information of these fields?

    Example like here:

    Screenshot 2022-12-28 at 17 24 41
    opened by Gilions 1
  • Get examples for custom schema

    Get examples for custom schema

    Describe the bug I am writing my own CustomAutoSchema class that inherits from AutoSchema. In one of my tests I check if every endpoint my API has a functional example. However, when I try to get the example from the custom schema I get an empty list. in openapi.py Autoschema there is the following function:

    def get_examples(self):
            """ override this for custom behaviour """
            return []
    

    How can I get the examples set in extend_schema_view decorator from a CustomAutoSchema object?

    To Reproduce This is the test:

    def helper_test_open_api_examples_work(
        viewset_class, user, objects, object_names, method="POST", view_kwargs=None
    ):
        if view_kwargs is None:
            view_kwargs = {}
        schema = viewset_class().schema
        schema.method = method
        schema.view.request = MagicMock()
        schema.view.kwargs = {}
        examples = schema.get_examples()
        assert len(examples) > 0
    

    Expected behavior Get correct examples from decorator

    opened by nour-bouzid 1
  • SlugRelatedField resolving fails on reverse ForeignKey

    SlugRelatedField resolving fails on reverse ForeignKey

    Describe the bug I have 2 models and a serializer

    class A(models.Model):
      name = models.CharField(max_length=100, unique=True)
    
    class B(models.Model):
      a = models.ForeignKey(A, on_delete=models.CASCADE)
      value = models.CharField(max_length=256)
    
    class ModelASerializer(serializers.ModelSerializer):
      bees = serializers.SlugRelatedField(many=True, slug_field="value", read_only=True, source="b_set")  # <-- Note this `X_set` here
      
      class Meta:
        model = A
        fields = "__all__"
    

    API call works perfectly as I get response like

    {
      "name": "my_unique_name",
      "bees": ["bee1", "bee2", "bee3"]
    }
    

    But drf-spectacular warns me about

    Users/hansaarne.liblik/code/my_project/serializers.py: Warning [view_as > ModelASerializer]: could not resolve field on model <class 'models.A'> with path "b_set.value". This is likely a custom field that does some unknown magic. Maybe consider annotating the field/property? Defaulting to "string". (Exception: A has no field named 'b_set')

    This happens, because get_field in target_model = model._meta.get_field(path[0]).related_model at /drf_spectacular/plumbing.py:552 does not find b_set from either self._forward_fields_map or self.fields_map.

    What it CAN find, is b (not b_set) in self.fields_map

    opened by HansAarneLiblik 0
  • fix: let use a default value for foreignkey model field

    fix: let use a default value for foreignkey model field

    If there is a default value in a model foreign key ('0' im my case), the actual code calls field.to_representation(field.default) and tries to interpret field.default.pk and raises an error. This fix let use raw default value.

    See Django documentation : https://docs.djangoproject.com/en/4.1/ref/models/fields/#default

    For fields like ForeignKey that map to model instances, defaults should be the value of the field they reference (pk unless to_field is set) instead of model instances.

    opened by freddez 2
  • `required` Property not properly reflected for `PrimaryKeyRelatedField`/`SlugRelatedField`

    `required` Property not properly reflected for `PrimaryKeyRelatedField`/`SlugRelatedField`

    Describe the bug The bug I found is two-folded. First thing I noticed is when having a PrimaryKeyRelatedField or SlugRelatedField where the target field is required, but the relationship is not, the required property is not documented correctly and that field is marked as required.

    I tried explicitly setting these fields to required=False, but they were still marked as required in the OpenAPI generated specs.

    To Reproduce

    models.py:
    class Parent(models.Model):
        target_field = models.CharField(max_length=100)
    
    
    class Child(models.Model):
        parent = models.ForeignKey(Parent, on_delete=models.SET_NULL, blank=True, null=True)
    
    serializers.py
    class ChildSerializer(serializers.ModelSerializer):
        class Meta:
            model = Child
            fields = ["parent_field"]
    
        parent_slug_field = serializers.SlugRelatedField(
            slug_field="target_field", source="parent", read_only=True, required=False
        )
        
        parent_field = serializers.PrimaryKeyRelatedField(
            slug_field="target_field", source="parent", read_only=True, required=False
        )
    

    Note that required=False is only needed for the second case I reported

    Expected behavior A SlugRelatedField/PrimaryKeyRelatedField should not be required on the children endpoints. Explicitly setting required=False should not be required, but in case it is given, the required property should be properly reflected in the documentation.

    opened by StopMotionCuber 2
Owner
T. Franzel
T. Franzel
Generating a report CSV and send it to an email - Python / Django Rest Framework

Generating a report in CSV format and sending it to a email How to start project. Create a folder in your machine Create a virtual environment python3

alexandre Lopes 1 Jan 17, 2022
Swagger Documentation Generator for Django REST Framework: deprecated

Django REST Swagger: deprecated (2019-06-04) This project is no longer being maintained. Please consider drf-yasg as an alternative/successor. I haven

Marc Gibbons 2.6k Jan 3, 2023
API spec validator and OpenAPI document generator for Python web frameworks.

API spec validator and OpenAPI document generator for Python web frameworks.

1001001 249 Dec 22, 2022
SqlAlchemy Flask-Restful Swagger Json:API OpenAPI

SAFRS: Python OpenAPI & JSON:API Framework Overview Installation JSON:API Interface Resource Objects Relationships Methods Custom Methods Class Method

Thomas Pollet 361 Nov 16, 2022
Test utility for validating OpenAPI documentation

DRF OpenAPI Tester This is a test utility to validate DRF Test Responses against OpenAPI 2 and 3 schema. It has built-in support for: OpenAPI 2/3 yaml

snok 106 Jan 5, 2023
Python Eacc is a minimalist but flexible Lexer/Parser tool in Python.

Python Eacc is a parsing tool it implements a flexible lexer and a straightforward approach to analyze documents.

Iury de oliveira gomes figueiredo 60 Nov 16, 2022
Flask-Rebar combines flask, marshmallow, and swagger for robust REST services.

Flask-Rebar Flask-Rebar combines flask, marshmallow, and swagger for robust REST services. Features Request and Response Validation - Flask-Rebar reli

PlanGrid 223 Dec 19, 2022
epub2sphinx is a tool to convert epub files to ReST for Sphinx

epub2sphinx epub2sphinx is a tool to convert epub files to ReST for Sphinx. It uses Pandoc for converting HTML data inside epub files into ReST. It cr

Nihaal 8 Dec 15, 2022
A simple document management REST based API for collaboratively interacting with documents

documan_api A simple document management REST based API for collaboratively interacting with documents.

Shahid Yousuf 1 Jan 22, 2022
Żmija is a simple universal code generation tool.

Żmija Żmija is a simple universal code generation tool. It is intended to be used as a means to generate code that is both efficient and easily mainta

Adrian Samoticha 2 Nov 23, 2021
Testing-crud-login-drf - Creation of an application in django on music albums

testing-crud-login-drf Creation of an application in django on music albums Befo

Juan 1 Jan 11, 2022
EasyModerationKit is an open-source framework designed to moderate and filter inappropriate content.

EasyModerationKit is a public transparency statement. It declares any repositories and legalities used in the EasyModeration system. It allows for implementing EasyModeration into an advanced character/word/phrase detection system.

Aarav 1 Jan 16, 2022
Code for our SIGIR 2022 accepted paper : P3 Ranker: Mitigating the Gaps between Pre-training and Ranking Fine-tuning with Prompt-based Learning and Pre-finetuning

P3 Ranker Implementation for our SIGIR2022 accepted paper: P3 Ranker: Mitigating the Gaps between Pre-training and Ranking Fine-tuning with Prompt-bas

null 14 Jan 4, 2023
🏆 A ranked list of awesome python developer tools and libraries. Updated weekly.

Best-of Python Developer Tools ?? A ranked list of awesome python developer tools and libraries. Updated weekly. This curated list contains 250 awesom

Machine Learning Tooling 646 Jan 7, 2023
ReStructuredText and Sphinx bridge to Doxygen

Breathe Packagers: PGP signing key changes for Breathe >= v4.23.0. https://github.com/michaeljones/breathe/issues/591 This is an extension to reStruct

Michael Jones 643 Dec 31, 2022
Watch a Sphinx directory and rebuild the documentation when a change is detected. Also includes a livereload enabled web server.

sphinx-autobuild Rebuild Sphinx documentation on changes, with live-reload in the browser. Installation sphinx-autobuild is available on PyPI. It can

Executable Books 440 Jan 6, 2023
An MkDocs plugin that simplifies configuring page titles and their order

MkDocs Awesome Pages Plugin An MkDocs plugin that simplifies configuring page titles and their order The awesome-pages plugin allows you to customize

Lukas Geiter 282 Dec 28, 2022
NetBox plugin that stores configuration diffs and checks templates compliance

Config Officer - NetBox plugin NetBox plugin that deals with Cisco device configuration (collects running config from Cisco devices, indicates config

null 77 Dec 21, 2022
Documentation generator for C++ based on Doxygen and mosra/m.css.

mosra/m.css is a Doxygen-based documentation generator that significantly improves on Doxygen's default output by controlling some of Doxygen's more unruly options, supplying it's own slick HTML+CSS generation and adding a fantastic live search feature.

Mark Gillard 109 Dec 7, 2022