django-rest-batteries


Namedjango-rest-batteries JSON
Version 1.4.1 PyPI version JSON
download
home_pagehttps://github.com/defineimpossible/django-rest-batteries
SummaryBuild clean APIs with DRF faster
upload_time2023-08-02 11:54:07
maintainer
docs_urlNone
authorDefine Impossible
requires_python>=3.8,<4.0
licenseMIT
keywords django rest framework drf django batteries
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            [![Test](https://github.com/defineimpossible/django-rest-batteries/actions/workflows/test.yml/badge.svg)](https://github.com/defineimpossible/django-rest-batteries/actions/workflows/test.yml)
[![Coverage](https://codecov.io/gh/defineimpossible/django-rest-batteries/branch/master/graph/badge.svg)](https://codecov.io/gh/defineimpossible/django-rest-batteries)

# Django REST Framework Batteries

Build clean APIs with DRF faster.

# Overview

Here's a quick overview of what the library has at the moment:

- Action-based serializers for ViewSets
- Two serializers per request/response cycle for ViewSets and GenericAPIViews
- Action-based permissions for ViewSets
- Single format for all errors

# Requirements

- Python ≥ 3.8
- Django ≥ 3.2
- Django REST Framework ≥ 3.12

# Installation

```bash
$ pip install django-rest-batteries
```

# Usage

## Action-based serializers for ViewSets

Each action can have a separate serializer:

```python
from rest_batteries.mixins import RetrieveModelMixin, ListModelMixin
from rest_batteries.viewsets import GenericViewSet
...

class OrderViewSet(RetrieveModelMixin,
                   ListModelMixin,
                   GenericViewSet):
    response_action_serializer_classes = {
        'retrieve': OrderSerializer,
        'list': OrderListSerializer,
    }
```

## Two serializers per request/response cycle

We found that more often than not we need a separate serializer for handling request payload and a separate serializer for generating response data.

How to achieve it in ViewSet:

```python
from rest_batteries.mixins import CreateModelMixin, ListModelMixin
from rest_batteries.viewsets import GenericViewSet
...

class OrderViewSet(CreateModelMixin,
                   ListModelMixin,
                   GenericViewSet):
    request_action_serializer_classes = {
        'create': OrderCreateSerializer,
    }
    response_action_serializer_classes = {
        'create': OrderResponseSerializer,
        'list': OrderResponseSerializer,
        'cancel': OrderResponseSerializer,
    }
```

How to achieve it in GenericAPIView:

```python
from rest_batteries.generics import CreateAPIView
...


class OrderCreateView(CreateAPIView):
    request_serializer_class = OrderCreateSerializer
    response_serializer_class = OrderResponseSerializer
```

## Action-based permissions for ViewSets

Each action can have a separate set of permissions:

```python
from rest_batteries.mixins import CreateModelMixin, UpdateModelMixin, ListModelMixin
from rest_batteries.viewsets import GenericViewSet
from rest_framework.permissions import AllowAny, IsAuthenticated
...

class OrderViewSet(CreateModelMixin,
                   UpdateModelMixin,
                   ListModelMixin,
                   GenericViewSet):
    action_permission_classes = {
        'create': IsAuthenticated,
        'update': [IsAuthenticated, IsOrderOwner],
        'list': AllowAny,
    }
```

## Single format for all errors

We believe that having a single format for all errors is good practice. This will make the process of displaying and handling errors much simpler for clients that use your APIs.

Any error always will be a JSON object with a message, code (identifier of the error), and field if the error is specific to a particular field. How your response could look like:

```python
{
    "errors": [
        {
            "message": "Delete or cancel all reservations first.",
            "code": "invalid"
        },
        {
            "message": "Ensure this field has no more than 21 characters.",
            "code": "max_length",
            "field": "address.work_phone"
        },
        {
            "message": "This email already exists",
            "code": "unique",
            "field": "login_email"
        }
    ]
}
```

You will not have a single format out-of-the-box after installation. You need to add an exception handler to your DRF settings:

```python
REST_FRAMEWORK = {
    ...
    'EXCEPTION_HANDLER': 'rest_batteries.exception_handlers.errors_formatter_exception_handler',
}
```

# Credits

- [Django-Styleguide by HackSoftware](https://github.com/HackSoftware/Django-Styleguide) - inspiration

            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/defineimpossible/django-rest-batteries",
    "name": "django-rest-batteries",
    "maintainer": "",
    "docs_url": null,
    "requires_python": ">=3.8,<4.0",
    "maintainer_email": "",
    "keywords": "django rest framework,drf,django,batteries",
    "author": "Define Impossible",
    "author_email": "hi@defineimpossible.io",
    "download_url": "https://files.pythonhosted.org/packages/90/27/b1aa26973f4ffb8a7ee39f1b8d4346786d3dd61431195c52fbeab0f96230/django_rest_batteries-1.4.1.tar.gz",
    "platform": null,
    "description": "[![Test](https://github.com/defineimpossible/django-rest-batteries/actions/workflows/test.yml/badge.svg)](https://github.com/defineimpossible/django-rest-batteries/actions/workflows/test.yml)\n[![Coverage](https://codecov.io/gh/defineimpossible/django-rest-batteries/branch/master/graph/badge.svg)](https://codecov.io/gh/defineimpossible/django-rest-batteries)\n\n# Django REST Framework Batteries\n\nBuild clean APIs with DRF faster.\n\n# Overview\n\nHere's a quick overview of what the library has at the moment:\n\n- Action-based serializers for ViewSets\n- Two serializers per request/response cycle for ViewSets and GenericAPIViews\n- Action-based permissions for ViewSets\n- Single format for all errors\n\n# Requirements\n\n- Python \u2265 3.8\n- Django \u2265 3.2\n- Django REST Framework \u2265 3.12\n\n# Installation\n\n```bash\n$ pip install django-rest-batteries\n```\n\n# Usage\n\n## Action-based serializers for ViewSets\n\nEach action can have a separate serializer:\n\n```python\nfrom rest_batteries.mixins import RetrieveModelMixin, ListModelMixin\nfrom rest_batteries.viewsets import GenericViewSet\n...\n\nclass OrderViewSet(RetrieveModelMixin,\n                   ListModelMixin,\n                   GenericViewSet):\n    response_action_serializer_classes = {\n        'retrieve': OrderSerializer,\n        'list': OrderListSerializer,\n    }\n```\n\n## Two serializers per request/response cycle\n\nWe found that more often than not we need a separate serializer for handling request payload and a separate serializer for generating response data.\n\nHow to achieve it in ViewSet:\n\n```python\nfrom rest_batteries.mixins import CreateModelMixin, ListModelMixin\nfrom rest_batteries.viewsets import GenericViewSet\n...\n\nclass OrderViewSet(CreateModelMixin,\n                   ListModelMixin,\n                   GenericViewSet):\n    request_action_serializer_classes = {\n        'create': OrderCreateSerializer,\n    }\n    response_action_serializer_classes = {\n        'create': OrderResponseSerializer,\n        'list': OrderResponseSerializer,\n        'cancel': OrderResponseSerializer,\n    }\n```\n\nHow to achieve it in GenericAPIView:\n\n```python\nfrom rest_batteries.generics import CreateAPIView\n...\n\n\nclass OrderCreateView(CreateAPIView):\n    request_serializer_class = OrderCreateSerializer\n    response_serializer_class = OrderResponseSerializer\n```\n\n## Action-based permissions for ViewSets\n\nEach action can have a separate set of permissions:\n\n```python\nfrom rest_batteries.mixins import CreateModelMixin, UpdateModelMixin, ListModelMixin\nfrom rest_batteries.viewsets import GenericViewSet\nfrom rest_framework.permissions import AllowAny, IsAuthenticated\n...\n\nclass OrderViewSet(CreateModelMixin,\n                   UpdateModelMixin,\n                   ListModelMixin,\n                   GenericViewSet):\n    action_permission_classes = {\n        'create': IsAuthenticated,\n        'update': [IsAuthenticated, IsOrderOwner],\n        'list': AllowAny,\n    }\n```\n\n## Single format for all errors\n\nWe believe that having a single format for all errors is good practice. This will make the process of displaying and handling errors much simpler for clients that use your APIs.\n\nAny error always will be a JSON object with a message, code (identifier of the error), and field if the error is specific to a particular field. How your response could look like:\n\n```python\n{\n    \"errors\": [\n        {\n            \"message\": \"Delete or cancel all reservations first.\",\n            \"code\": \"invalid\"\n        },\n        {\n            \"message\": \"Ensure this field has no more than 21 characters.\",\n            \"code\": \"max_length\",\n            \"field\": \"address.work_phone\"\n        },\n        {\n            \"message\": \"This email already exists\",\n            \"code\": \"unique\",\n            \"field\": \"login_email\"\n        }\n    ]\n}\n```\n\nYou will not have a single format out-of-the-box after installation. You need to add an exception handler to your DRF settings:\n\n```python\nREST_FRAMEWORK = {\n    ...\n    'EXCEPTION_HANDLER': 'rest_batteries.exception_handlers.errors_formatter_exception_handler',\n}\n```\n\n# Credits\n\n- [Django-Styleguide by HackSoftware](https://github.com/HackSoftware/Django-Styleguide) - inspiration\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "Build clean APIs with DRF faster",
    "version": "1.4.1",
    "project_urls": {
        "Homepage": "https://github.com/defineimpossible/django-rest-batteries",
        "Repository": "https://github.com/defineimpossible/django-rest-batteries"
    },
    "split_keywords": [
        "django rest framework",
        "drf",
        "django",
        "batteries"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "19a02638f2da83ba198a76179e194b1ac3db5e4d2e780ceb5f7de42f17c2355e",
                "md5": "3f23ce5917bcff1d385d1fd9678e06da",
                "sha256": "236918b0671bdb12fd13240ae56df78512d0552cb3de4799509164e3629ef20c"
            },
            "downloads": -1,
            "filename": "django_rest_batteries-1.4.1-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "3f23ce5917bcff1d385d1fd9678e06da",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.8,<4.0",
            "size": 8971,
            "upload_time": "2023-08-02T11:54:05",
            "upload_time_iso_8601": "2023-08-02T11:54:05.217798Z",
            "url": "https://files.pythonhosted.org/packages/19/a0/2638f2da83ba198a76179e194b1ac3db5e4d2e780ceb5f7de42f17c2355e/django_rest_batteries-1.4.1-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "9027b1aa26973f4ffb8a7ee39f1b8d4346786d3dd61431195c52fbeab0f96230",
                "md5": "98e12ebdb9f052287f4593011a4d784c",
                "sha256": "7ee0ce97c0c678dbc2949aba011d7170c61a525bece83986c7e8f5698698f768"
            },
            "downloads": -1,
            "filename": "django_rest_batteries-1.4.1.tar.gz",
            "has_sig": false,
            "md5_digest": "98e12ebdb9f052287f4593011a4d784c",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.8,<4.0",
            "size": 8837,
            "upload_time": "2023-08-02T11:54:07",
            "upload_time_iso_8601": "2023-08-02T11:54:07.641202Z",
            "url": "https://files.pythonhosted.org/packages/90/27/b1aa26973f4ffb8a7ee39f1b8d4346786d3dd61431195c52fbeab0f96230/django_rest_batteries-1.4.1.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2023-08-02 11:54:07",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "defineimpossible",
    "github_project": "django-rest-batteries",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "lcname": "django-rest-batteries"
}
        
Elapsed time: 0.60228s