Metadata-Version: 2.1
Name: drf-serialization-magic
Version: 1.0.3
Summary: Open package for Django Rest Framework to reduce the duplication of code when working with Serializer
Home-page: https://github.com/tkppro/drf-serialization-magic
Author: Thang Dang Minh
Author-email: thangdangdev@gmail.com
License: BSD
Classifier: Development Status :: 5 - Production/Stable
Classifier: Environment :: Web Environment
Classifier: Framework :: Django
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: BSD License
Classifier: Operating System :: OS Independent
Classifier: Natural Language :: English
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.6
Classifier: Programming Language :: Python :: 3.7
Classifier: Programming Language :: Python :: 3.8
Classifier: Topic :: Internet :: WWW/HTTP
Requires-Python: >=3.7
Description-Content-Type: text/markdown
License-File: LICENSE

# DRF Serialization Magic

**A collection of useful Decorators to DRY up your Django Rest Framework project when working with Serializers**

Full documentation on [read the docs](https://drf-serialization-magic.readthedocs.io/en/latest/)

## Overview

Serialization magic helps you boost your code and reduce duplication
by using a higher-order function to reduce the number of lines of code
and maintain consistency in your project.

## Requirements

- Python (>= 3.7)
- [Django](https://github.com/django/django) (>= 3.0)
- [Django REST Framework](https://github.com/tomchristie/django-rest-framework) (> 3.11)

## Installation

Using `pip`:

```bash
$ pip install drf-serialization-magic
```

## Basic Usage

**RenderSerialization**

```py
# model user
from django.contrib.auth.models import AbstractUser

class User(AbstractUser):
    pass
```

```py
# serializers.py
from rest_framework import serializers
from drf_serialization_magic.models import User

class UserInformationSerializer(serializers.ModelSerializer):
    email = serializers.EmailField()
    username = serializers.CharField()

    class Meta:
        model = User
        fields = ["id", "email", "username"]
```

- With `@api_view` decorator function

```py
from rest_framework.decorators import api_view
from drf_serialization_magic import RenderSerialization
from drf_serialization_magic.serializers import UserInformationSerializer

@api_view(http_method_names=["GET"])
@RenderSerialization(serializer_cls=UserInformationSerializer)
def get_user_func_view(request):
    return request.user
```

API response

```json
{
  "data": {
    "id": 1,
    "email": "userA@example.com",
    "username": "userA"
  }
}
```

- With `GenericViewSet` class

```py
from drf_serialization_magic import RenderSerialization
from rest_framework.viewsets import GenericViewSet
from drf_serialization_magic.models import User
from drf_serialization_magic.serializers import UserInformationSerializer
# ...


class UserViewSet(GenericViewSet):
    def get_queryset(self):
        return User.objects.all()

    @RenderSerialization(serializer_cls=UserInformationSerializer)
    def list(self, request):
        return self.get_queryset()
```

API response

```json
{
  "count": 2,
  "next": null,
  "previous": null,
  "data": [
    {
      "id": 1,
      "email": "tom_hiddleston@gmail.com",
      "username": "tom_hiddleston"
    },
    {
      "id": 2,
      "email": "chris_hemsworth@gmail.com",
      "username": "chris_hemsworth"
    }
  ]
}
```

- With `APIView` class

```py
from rest_framework.views import APIView
from drf_serialization_magic import RenderSerialization
from drf_serialization_magic.serializers import UserInformationSerializer


class UserAPIView(APIView):
    @RenderSerialization(serializer_cls=UserInformationSerializer)
    def get(self, request):
        return request.user
```

**ValidateSerialization**

- When validating body data(`POST` method)

```py
from rest_framework.views import APIView
from drf_serialization_magic import RenderSerialization, ValidateSerialization
from drf_serialization_magic.serializers import UserInformationSerializer
from drf_serialization_magic.models import User


# combination usage
class UserAPIView(APIView):
    @RenderSerialization(serializer_cls=UserInformationSerializer)
    @ValidateSerialization(serializer_cls=UserInformationSerializer, location="body")
    def create(self, request, data):
        # data object is validated
        # the default will use key `data`, if you want to use another key,
        # pass argument to_key="something" in ValidateSerialization
        user = User.objects.create(**data)
        return user
```

API call

```bash
POST /api/users HTTP/1.1
Host: 127.0.0.1
Content-Type: application/json
Accept: */*


{
  "email": "chris.evans",
  "username": "chris_evans"
}

```

API response (422 HTTP status's code)

```json
{
  "errors": [
    {
      "field": "email",
      "detail": ["Enter a valid email address."]
    }
  ],
  "message": "Validation Error!"
}
```

- When validating query params

```py
from drf_serialization_magic import RenderSerialization, ValidateSerialization
from drf_serialization_magic.serializers import UserInformationSerializer
from drf_serialization_magic.models import User
from rest_framework.viewsets import GenericViewSet


class UserViewSet(GenericViewSet):

    # combination usage
    @RenderSerialization(serializer_cls=UserInformationSerializer)
    @ValidateSerialization(serializer_cls=UserInformationSerializer, location="query")
    def list(self, request, query):
        # data dict is validated
        # the default will use key `data`, if you want to use another key,
        # pass argument to_key="something" in ValidateSerialization
        user = User.objects.filter(username=query["username"])
        return user
```

API call

```
GET /api/users?email=chris_evans HTTP/1.1
```

API response(422 HTTP status's code)

```json
{
  "errors": [
    {
      "field": "email",
      "detail": ["Enter a valid email address."]
    }
  ],
  "message": "Validation Error!"
}
```

Accept list query params lookup:

```py
from drf_serialization_magic import RenderSerialization, ValidateSerialization
from drf_serialization_magic.serializers import UserListLookUpSerializer, UserInformationSerializer
    
from drf_serialization_magic.models import User
from rest_framework.viewsets import GenericViewSet


class UserViewSet(GenericViewSet):

    # combination usage
    @RenderSerialization(serializer_cls=UserInformationSerializer)
    @ValidateSerialization(serializer_cls=UserListLookUpSerializer, location="query")
    def list(self, request, query):
        # query dict is validated
        # the default will use key `query`, if you want to use another key,
        # pass argument to_key="something" in ValidateSerialization
        user = User.objects.filter(username__in=query["username"])
        return user
```

API request

```
GET /api/users?username=chris_evans&username=tom_hiddleston HTTP/1.1
```

API response

```json
{
  "count": 2,
  "next": null,
  "previous": null,
  "data": [
    {
      "id": 1,
      "email": "tom_hiddleston@gmail.com",
      "username": "tom_hiddleston"
    },
    {
      "id": 3,
      "email": "chris.evans@gmail.com",
      "username": "chris_evans"
    }
  ]
}
```

## Testing

Tested with:

- Python (>= 3.9)
- [Django](https://github.com/django/django) (>= 3.1)
- [Django REST Framework](https://github.com/tomchristie/django-rest-framework) (> 3.11)


## Support

If you need help, don't hesitate to start an [issue][issue].
For commercial support, please contact via email:
[Thang Dang Minh](mailto:thangdangdev@gmail.com?subject=[GitHub]%20Source%20Django%20Serialization%20Magic)

[issue]: https://github.com/tkppro/drf-serialization-magic/issues
