drf-spectacular

repository·master·Indexed 25 days ago

https://github.com/tfranzel/drf-spectacular

A sane and flexible OpenAPI (3.0.3, 3.1, 3.2) schema generation library for Django REST framework. It extracts information from DRF to ensure compatibility with popular client generators and provides tools for customization via decorators like @extend_schema, @extend_schema_view, and @extend_schema_field, as well as extension blueprints and postprocessing hooks.

Tokens
19.4K
Snippets
44
Records
101
Agent score
84%

What's inside drf-spectacular

  1. Configure django-rest-knox for OpenAPI compatibility

    master

    While django-rest-knox auth extensions are supported natively, the Views may lack structure in the generated OpenAPI document. Use the provided blueprint to fix this.

    Additionally, to ensure out-of-the-box compatibility with OpenAPI generators and Swagger UI, configure the standard Authorization header prefix in your settings:

    REST_KNOX = {
        "AUTH_HEADER_PREFIX": "Bearer",
    }
  2. Migrate docstring parsing from drf-yasg to drf-spectacular

    master

    Unlike drf-yasg, which splits docstrings into a summary (first line) and description (remainder), drf-spectacular uses the entire docstring as the operation description.

    To achieve the same granular control as drf-yasg, use the summary and description arguments within the @extend_schema decorator. If you want to use a docstring for the description but a custom summary, provide the summary via the decorator and keep the docstring for the description.

    For ViewSets where drf-yasg used named sections within a class-level docstring, use @extend_schema_view to apply specific @extend_schema configurations to individual methods.

    # Using decorator for explicit summary and description
    class UserViewSet(ViewSet):
        @extend_schema(
            summary="List all the users.",
            description="Return a list of all usernames in the system.",
        )
        def list(self, request):
            ...
    
    # Using decorator for summary and docstring for description
    class UserViewSet(ViewSet):
        @extend_schema(summary="List all the users.")
        def list(self, request):
            """Return a list of all usernames in the system."""
            ...
    
    # Replacing class-level docstring sections with @extend_schema_view
    @extend_schema_view(
        list=extend_schema(
            summary="List all the users.",
            description="Return a list of all usernames in the system.",
        ),
        retrieve=extend_schema(
            summary="Retrieve user",
            description="Get details of a specific user",
        ),
    )
    class UserViewSet(ViewSet):
        ...
  3. Migrate from drf-yasg to drf-spectacular decorators

    master

    If you are migrating from drf-yasg, replace your decorators with the following drf-spectacular equivalents. Note the changes in argument names:

    • Replace @swagger_auto_schema with @extend_schema.

      • operation_description $\rightarrow$ description
      • operation_summary $\rightarrow$ summary
      • manual_parameters and query_serializer $\rightarrow$ parameters
      • security $\rightarrow$ auth
      • request_body $\rightarrow$ request (use None instead of drf_yasg.utils.no_body)
      • method $\rightarrow$ methods
      • Additional arguments: exclude, operation, versions, examples.
    • Replace @swagger_serializer_method with @extend_schema_field.

    • Replace @method_decorator with @extend_schema_view to decorate entire views.

    • Replace swagger_schema_field with @extend_schema_field or @extend_schema_serializer.

  4. Migrate from drf-yasg to drf-spectacular helper classes

    master

    When migrating helper classes from drf-yasg to drf-spectacular, use these mappings:

    • drf_yasg.openapi.Parameter $\rightarrow$ drf_spectacular.utils.OpenApiParameter.

      • in_ $\rightarrow$ location
      • schema $\rightarrow$ type
      • Use many=True to define an array (replaces the need for an Items class).
    • drf_yasg.openapi.Response $\rightarrow$ drf_spectacular.utils.OpenApiResponse.

      • schema $\rightarrow$ response
      • Note: Use keyword arguments as the order of arguments differs.
    • drf_yasg.openapi.Schema is no longer required; use a plain Python dict instead.

    • Use drf_spectacular.utils.OpenApiExample to provide examples to @extend_schema.

  5. Handle get_queryset() dependencies during schema generation

    master

    If get_queryset() or get_serializer_class() depends on attributes not available during schema generation (like request.user), you must provide a fallback. Check for the swagger_fake_view attribute on the view and return an empty queryset of the correct model.

    class XViewset(viewsets.ModelViewset):
        ...
    
        def get_queryset(self):
            if getattr(self, 'swagger_fake_view', False):
                return YourModel.objects.none()
            # your usual logic
    class XViewset(viewsets.ModelViewset):
        ...
    
        def get_queryset(self):
            if getattr(self, 'swagger_fake_view', False):
                return YourModel.objects.none()
            # your usual logic
  6. Configure Authentication schemes in drf-spectacular

    master

    While drf-yasg required manual description of authentication schemes, drf-spectacular automatically generates security definitions for many built-in DRF authentication classes and popular third-party packages.

    To integrate custom authentication classes, implement the drf_spectacular.extensions.OpenApiAuthenticationExtension class.

  7. Ensure schema extensions are detected

    master

    Extensions register themselves automatically, but the Python interpreter must see them at least once. The most robust way to ensure detection is to collect extensions in a schema.py file within your main app and import that file in your app's ready() method inside apps.py.

    # your_main_app_name/apps.py
    class YourMainAppNameConfig(AppConfig):
        default_auto_field = "django.db.models.BigAutoField"
        name = "your_main_app_name"
    
        def ready(self):
            import your_main_app_name.schema  # noqa: E402
    # your_main_app_name/apps.py
    class YourMainAppNameConfig(AppConfig):
        default_auto_field = "django.db.models.BigAutoField"
        name = "your_main_app_name"
    
        def ready(self):
            import your_main_app_name.schema  # noqa: E402
  8. Register Extension Blueprints in your Django app

    master

    Blueprints are schema fixes for libraries that do not play well with drf-spectacular's automatic introspection. To use a blueprint, copy the snippet into your codebase. The extensions register themselves automatically as long as the Python interpreter sees them.

    It is best practice to collect your extensions in YOUR_MAIN_APP_NAME/schema.py and import that file in your YOUR_MAIN_APP_NAME/apps.py within the ready() method to ensure the environment is properly set up.

    # your_main_app_name/apps.py
    class YourMainAppNameConfig(AppConfig):
        default_auto_field = "django.db.models.BigAutoField"
        name = "your_main_app_name"
    
        def ready(self):
            import your_main_app_name.schema  # noqa: E402
  9. Install drf-spectacular with sidecar for offline environments

    master

    If your environment cannot access CDNs to retrieve Swagger UI or Redoc, install the sidecar extra. This provides the static files locally. You must add drf_spectacular_sidecar to INSTALLED_APPS and configure the SPECTACULAR_SETTINGS to use the SIDECAR shorthand.

    $ pip install drf-spectacular[sidecar]
    INSTALLED_APPS = [
        # ALL YOUR APPS
        'drf_spectacular',
        'drf_spectacular_sidecar',  # required for Django collectstatic discovery
    ]
    
    SPECTACULAR_SETTINGS = {
        'SWAGGER_UI_DIST': 'SIDECAR',  # shorthand to use the sidecar instead
        'SWAGGER_UI_FAVICON_HREF': 'SIDECAR',
        'REDOC_DIST': 'SIDECAR',
        # OTHER SETTINGS
    }
  10. Register Extensions via AppConfig.ready()

    master

    Extensions in drf-spectacular register themselves automatically, but the Python interpreter must see them at least once. The most robust way to ensure extensions are loaded is to collect them in a schema.py file within your main app and import that file inside the ready() method of your AppConfig in apps.py.

    # your_main_app_name/apps.py
    class YourMainAppNameConfig(AppConfig):
        default_auto_field = "django.db.models.BigAutoField"
        name = "your_main_app_name"
    
        def ready(self):
            import your_main_app_name.schema  # noqa: E402
  11. Run tests for drf-spectacular

    master

    To run the project's test suite, you can use the provided runtests.py script or tox for testing against multiple Python and Django versions.

    1. Install testing requirements: pip install -r requirements.txt
    2. Run tests using the local script: ./runtests.py
    3. Alternatively, use tox (requires tox to be installed globally): tox
    $ pip install -r requirements.txt
    $ ./runtests.py
    # OR
    $ tox