Skip to main content

saritasa-drf-tools

GitHub last commit GitHub Workflow Status (with event) PyPI PyPI - Status PyPI - Python Version PyPI - Django Version PyPI - License PyPI - Downloads Ruff prek

Check out our other open-source projects

Tools For DRF Used By Saritasa

Table of contents

Installation

pip install saritasa-drf-tools

or if you are using uv

uv add saritasa-drf-tools

or if you are using poetry

poetry add saritasa-drf-tools

Features

  • Views - collection of mixins and viewsets classes
  • Serializers - collection of mixins and serializers classes
  • Filters - Custom filter backends that improve integration with drf-spectacular
  • OpenAPI - tools for drf-spectacular
  • pytest - plugin which provides different api_client fixtures.
  • Testing classes(Warning: Very experimental) - Test class which contains shortcut to reduce boilerplate across tests.

For examples and to just check it out in action you can use example folder.

Optional dependencies

  • [filters] - Add this to enable django-filters support
  • [openapi] - Add this to enable drf-spectacular support

Views

Views mixins

  • ActionPermissionsMixin: Mixin which allows to define specific permissions per actions For example you have:

    class CRUDView(
      ActionPermissionsMixin,
      ActionMixins, # Anything you need
      GenericViewSet,
    ):
      """CRUD view."""
      base_permission_classes = (permissions.AllowAny,)
      extra_permission_classes = (permissions.IsAuthenticated,)
      extra_permissions_map = {
          "create": (permissions.IsAdminUser,),
          "update": (permissions.IsAdminUser,),
          "destroy": (permissions.IsAdminUser,),
      }
    
    • base_permission_classes - Will be applied to any action (Usually you want this in base class of your project)
    • extra_permission_classes - Will be added to base_permission_classes
    • extra_permission_map - Will be added to (base_permission_classes + extra_permission_classes) on action you specify in mapping

    To learn more read class docs.

  • ActionSerializerMixin: Mixin which allows to define specific serializers per action. For example you have

    class CRUDView(
      ActionPermissionsMixin,
      ActionMixins, # Anything you need
      GenericViewSet,
    ):
      """CRUD view."""
    
      queryset = models.TestModel.objects.select_related("related_model").all()
      serializers_map = {
          "default": serializers.TestModelDetailSerializer,
          "list": serializers.TestModelListSerializer,
      }
    

    That means that on list view will use TestModelListSerializer, but on any other actions TestModelDetailSerializer. This will also will be reflected in generated openapi specs via drf-spectacular

    To learn more read class docs.

  • UpdateModelWithoutPatchMixin: Same as UpdateModelMixin but without patch method

Viewset classes

  • BaseViewSet: Viewset with ActionPermissionsMixin and ActionSerializerMixin
  • CRUDViewSet: Viewset with crud endpoint based on BaseViewSet
  • ReadOnlyViewSet: Viewset with read endpoint based on BaseViewSet

Pagination

  • LimitOffsetPagination: Customized paginator class to limit max objects in list APIs. Use SARITASA_DRF_MAX_PAGINATION_SIZE to set default max for whole project. Also supports overriding pagination settings per view via pagination_default_limit and pagination_max_limit attributes.

Serializers

Serializers mixins

  • CleanValidationMixin: Enable model clean validation in serializer

  • FieldMappingOverride: Override or extend field mapping via SARITASA_DRF_FIELD_MAPPING. For example you can set following in settings.

    SARITASA_DRF_FIELD_MAPPING = {
      "django.db.models.TextField": "example.app.api.fields.CustomCharField",
    }
    

    And now all TextField of your models will have CustomCharField in serializers.

  • UserAndRequestFromContextMixin: Extracts user and request from context and sets it as attr of serializer instance.

  • NestedFieldsMixin: Allows to define nested data fields for serializers via Meta class.

Serializers classes

  • BaseSerializer: Serializer with UserAndRequestFromContextMixin
  • ModelBaseSerializer: ModelSerializer with mixins.FieldMappingOverride, mixins.CleanValidationMixin, mixins.UserAndRequestFromContextMixin, mixins.NestedFieldsMixin.

Filters

Needs filters and openapi to be included to work properly.

  • OrderingFilterBackend: Add supported fields to ordering param's description in specs generated by drf-spectacular. Will raise warning specs validation on empty ordering_fields or if queryset is unable to order itself using ordering_fields. Example of description:

    Which fields to use when ordering the results. A list fields separated by ,. Example: field1,field2
    
    Supported fields: id, text_field, related_model__text_field.
    
    To reverse order just add - to field. Example:field -> -field
    

    Also has support for nulls_first and nulls_last ordering. You can either set these options globally in your settings:

    SARITASA_DRF_ORDERING_IS_NULL_FIRST = True
    SARITASA_DRF_ORDERING_IS_NULL_LAST = True
    

    Or you can set them per view:

    class MyView(views.APIView):
        ordering_fields_extra_kwargs = {
            "my_field": {
                "nulls_first": True,
                "nulls_last": False,
            },
        }
    

    If you have list of items ordered by non-unique fields only (or without any ordering), this filter will add secondary sorting by pk to make sure that order of items will be consistent across requests. You can enable secondary sorting via add_pk_to_ordering flag in your views:

    class MyView(views.APIView):
        add_pk_to_ordering = True
    

    By default, this option is enabled. You can either set this option globally in your settings:

    SARITASA_DRF_ORDERING_ADD_PK_TO_ORDERING = True
    
  • SearchFilterBackend: Add supported fields to search param's description in specs generated by drf-spectacular. Will raise warning specs validation on empty search_fields or if queryset is unable to perform search using search_fields.

    Example of description:

    A search term.
    
    Performed on this fields: text_field, related_model__text_field.
    
  • DjangoFilterBackend: Customized DjangoFilterBackend to reduce queries count when viewing api requests via browser

Renderers

  • BrowsableAPIRenderer: Customization over drf's BrowsableAPIRenderer. With SARITASA_DRF_BROWSABLE_API_ENABLE_HTML_FORM(Default: True) or setting enable_browsable_api_rendered_html_form(If not present will use global setting) in view you can disable all extra forms which results in extra SQL queries.

OpenAPI

Needs openapi to be included to work properly.

  • OpenApiSerializer: Serializer that should be used for customizing open_api spec. Made to avoid warnings about unimplemented methods.
  • DetailSerializer: To show in spec responses like this {detail: text}.
  • fix_api_view_warning: Fix warning This is graceful fallback handling for APIViews.

Pytest

Plugin provides following fixtures:

  • api_client_factory - factory which generated rest_framework.test.ApiClient instance
  • api_client - uses api_client_factory to generate rest_framework.test.ApiClient instance
  • user_api_client(Needs user fixture) uses api_client_factory to generate rest_framework.test.ApiClient instance forces auth to user
  • admin_api_client(Needs admin fixture) uses api_client_factory to generate rest_framework.test.ApiClient instance forces auth to admin

Tester

Warning: Very experimental.

saritasa_drf_tools.testing.ApiActionTester - is a tester class which contains fixtures and shortcuts to simply and reduce boilerplate in tests for viewsets.

All you need to is create tester.py(you what ever you want it's just recommendation). In this file declare new class which inherits ApiActionTester.

class CRUDApiActionTester(
    saritasa_drf_tools.testing.ApiActionTester.init_subclass(
        model=models.TestModel, # Model of queryset in viewset
        user_model=models.User, # Model of user used across project
        factory=factories.TestModelFactory, # Factory which is used to generate instances for model
        api_view=api.views.CRUDView, # Class of viewset against which we will be writing tests
        url_basename="crud-api", # Base name of urls of viewset. {url_basename}-{action}
    ),
):
    """Tester for crud API."""

Next you can write test just like this. (For more examples check this folder: tests/test_crud_api)

class TestCRUD(tester.CRUDApiActionTester):
    """Define tests."""

    @pytest.mark.parametrize(
        argnames=[
            "parametrize_user",
            "status_code",
        ],
        argvalues=[
            [
                None,
                status.HTTP_403_FORBIDDEN,
            ],
            [
                pytest_lazy_fixtures.lf("user"),
                status.HTTP_403_FORBIDDEN,
            ],
            [
                pytest_lazy_fixtures.lf("admin"),
                status.HTTP_201_CREATED,
            ],
        ],
    )
    def test_permission_map_specified_action_create(
        self,
        instance: tester.CRUDApiActionTester.model,
        parametrize_user: tester.CRUDApiActionTester.user_model | None,
        status_code: int,
    ) -> None:
        """Test that create action will properly handle permissions."""
        self.make_request(
            method="post",
            user=parametrize_user,
            expected_status=status_code,
            path=self.lazy_url(action="list"),
            data=self.serialize_data(action="create", data=instance),
        )

Metadata

Release files for saritasa-drf-tools 0.4.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for saritasa-drf-tools 0.4.0
File Size Uploaded
saritasa_drf_tools-0.4.0.tar.gz 124.8 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for saritasa-drf-tools 0.4.0
File Interpreter ABI Platform
saritasa_drf_tools-0.4.0-py3-none-any.whl Python 3 none any Details

Total release size: 152.0 kB

Release files / saritasa_drf_tools-0.4.0.tar.gz

Download URL saritasa_drf_tools-0.4.0.tar.gz
Size 124.8 kB
Tags Source
SHA-256 checksum
How to use checksums
df95cd20c7787d67b60598b111174b90e9fae566593bafd3c2f3e04895074d45
BLAKE2b-256 checksum
How to use checksums
4bfdc2a5939c1bbd3e852fdd7fba59c99eb581a13d26dce43fe16892a9139427
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.11.24 {"installer":{"name":"uv","version":"0.11.24","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / saritasa_drf_tools-0.4.0-py3-none-any.whl

Download URL saritasa_drf_tools-0.4.0-py3-none-any.whl
Size 27.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
695a135cfebd6f4b70309686bc7c689e53e0b2828beb69f75f3dc2d3e8169868
BLAKE2b-256 checksum
How to use checksums
f2a6f1a8607054f554c0c3c274d886370a61aebb6b2e775691e91ad51151116c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.11.24 {"installer":{"name":"uv","version":"0.11.24","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release history Release notifications | RSS feed

This release

0.4.0 This release

2 release files

0.3.0

2 release files

0.2.2

2 release files

0.2.1

2 release files

0.2.0

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page