🚀 Big News: Socket Acquires Coana to Bring Reachability Analysis to Every Appsec Team.Learn more
Socket
Sign inDemoInstall
Socket

drf-apischema

Package Overview
Dependencies
Maintainers
1
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

drf-apischema

API schema generator and validator for Django REST framework

0.2.5
PyPI
Maintainers
1

DRF APISchema

Based on drf-spectacular, automatically generate API documentation, validate queries, bodies, and permissions, handle transactions, and log SQL queries.
This can greatly speed up development and make the code more readable.

Features

  • Auto generate API documentation and routes

  • Validate queries, bodies, and permissions

  • Handle transactions

  • Log SQL queries

  • Simple to use

@apischema(permissions=[IsAdminUser], body=UserIn, response=UserOut)
def create(self, request: ASRequest[UserIn]):
    """Description"""
    print(request.serializer, request.validated_data)
    return UserOut(request.serializer.save()).data

Installation

Install drf-apischema from PyPI

pip install drf-apischema

Configure your project settings.py like this

INSTALLED_APPS = [
    # ...
    "rest_framework",
    "drf_spectacular",
    # ...
]

REST_FRAMEWORK = {
    "DEFAULT_SCHEMA_CLASS": "drf_spectacular.openapi.AutoSchema",
}

SPECTACULAR_SETTINGS = {
    "TITLE": "Your Project API",
    "DESCRIPTION": "Your project description",
    "VERSION": "1.0.0",
    "SERVE_INCLUDE_SCHEMA": False,
    'SCHEMA_PATH_PREFIX': '/api',
}

Usage

serializers.py

from django.contrib.auth.models import User
from rest_framework import serializers


class UserOut(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = ["id", "username"]


class SquareOut(serializers.Serializer):
    result = serializers.IntegerField()


class SquareQuery(serializers.Serializer):
    n = serializers.IntegerField(default=2)

views.py

from typing import Any

from django.contrib.auth.models import User
from rest_framework.decorators import action
from rest_framework.mixins import ListModelMixin, RetrieveModelMixin
from rest_framework.permissions import IsAdminUser, IsAuthenticated
from rest_framework.viewsets import GenericViewSet

from drf_apischema import ASRequest, apischema, apischema_view

from .serializers import SquareOut, SquareQuery, UserOut

# Create your views here.


@apischema_view(
    retrieve=apischema(summary="Retrieve a user"),
)
class UserViewSet(GenericViewSet, ListModelMixin, RetrieveModelMixin):
    """User management"""

    queryset = User.objects.all()
    serializer_class = UserOut
    permission_classes = [IsAuthenticated]

    # Define a view that requires permissions
    @apischema(permissions=[IsAdminUser])
    def list(self, request):
        """List all

        Document here
        xxx
        """
        return super().list(request)

    # will auto wrap it with `apischema` in `apischema_view`
    @action(methods=["post"], detail=True)
    def echo(self, request, pk):
        """Echo the request"""
        return self.get_serializer(self.get_object()).data

    @apischema(query=SquareQuery, response=SquareOut)
    @action(methods=["get"], detail=False)
    def square(self, request: ASRequest[SquareQuery]) -> Any:
        """The square of a number"""
        # The request.serializer is an instance of SquareQuery that has been validated
        # print(request.serializer)

        # The request.validated_data is the validated data of the serializer
        n: int = request.validated_data["n"]

        # Note that apischema won't automatically process the response with the declared response serializer,
        # but it will wrap it with rest_framework.response.Response
        # So you don't need to manually wrap it with Response
        return SquareOut({"result": n * n}).data

urls.py

from django.urls import include, path
from rest_framework.routers import DefaultRouter

from drf_apischema.urls import api_path

from .views import *

router = DefaultRouter()
router.register("test", TestViewSet, basename="test")


urlpatterns = [
    # Auto-generate /api/schema/, /api/schema/swagger/ and /api/schema/redoc/ for documentation
    api_path("api/", [path("", include(router.urls))])
]

settings

settings.py

DRF_APISCHEMA_SETTINGS = {
    # Enable transaction wrapping for APIs
    "TRANSACTION": True,
    # Enable SQL logging
    "SQL_LOGGING": True,
    # Indent SQL queries
    "SQL_LOGGING_REINDENT": True,
    # Use method docstring as summary and description
    "SUMMARY_FROM_DOC": True,
    # Show permissions in description
    "SHOW_PERMISSIONS": True,
    # If True, request_body and response will be empty by default if the view is action decorated
    "ACTION_DEFAULTS_EMPTY": True,
}

drf-yasg version

See branch drf-yasg, it is not longer supported

Troubleshooting

Doesn't showed permissions description of permission_classes

Wrap the view with apischema_view.

@apischema_view()
class XxxViewSet(GenericViewSet):
    permissions_classes = [IsAuthenticated]

TypeError: cannot be assigned to parameter of type "_View@action"

Just annotate the return type to Any, as apischema will wrap it with Response.

@apischema()
@action(methods=["get"], detail=False)
def xxx(self, request) -> Any:
    ...

Keywords

django

FAQs

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts