An alternative serializer implementation for REST framework written in cython built for speed.
Project description
drf-turbo
An alternative serializer implementation for REST framework written in cython built for speed.
- Free software: MIT license
- Documentation: https://drf-turbo.readthedocs.io.
NOTE: Cython is required to build this package.
Requirements
- Django
- Django REST Framework
- Cython
- forbiddenfruit
- pyyaml(OpenAPI)
- uritemplate(OpenAPI)
- djangorestframework-simplejwt(OpenAPI)
Installation
$ pip install drf-turbo
Declaring Serializers
from datetime import datetime from django.utils.timezone import now import drf_turbo as dt class User: def __init__(self, username, email,created=None): self.username = username self.email = email self.created = created or datetime.now() user = User(username='test' , email='test@example.com') class UserSerializer(dt.Serializer): username = dt.StrField(max_length=50) email = dt.EmailField() created = dt.DateTimeField()
Serializing objects
serializer = UserSerializer(user) serializer.data # {'username': 'test', 'email': 'test@example.com', 'created': '2021-11-04T22:49:01.981127Z'}
Deserializing objects
data = {'username':'new_test','email':'test2@example.com','created':now()} serializer = UserSerializer(data=data) serializer.is_valid() # True serializer.validated_data # {'username': 'new_test', 'email': 'test2@example.com', 'created': datetime.datetime(2021, 11, 12, 6, 10, 44, 85118)}}
Validation
serializer = UserSerializer(data={'email': 'test'}) serializer.is_valid() # False serializer.errors # {'username': ['This field is required.'], 'email': ['Enter a valid email address.'],'created': ['This field is required.']}
Field-level validation
import drf_turbo as dt class UserSerializer(dt.Serializer): username = dt.StrField(max_length=50) def validate_username(self, value): if 'test' not in value.lower(): raise dt.ValidationError("test must be in username") return value
Object-level validation
import drf_turbo as dt class CampaignSerializer(dt.Serializer): start_date = dt.DateTimeField() end_date = dt.DateTimeField() def validate(self, data): if data['start_date'] > data['end_date']: raise dt.ValidationError("start_date must occur before end_date") return data
Nested Serializers
from datetime import datetime from django.utils.timezone import now import drf_turbo as dt class User: def __init__(self, username, email,created=None): self.username = username self.email = email self.created = created or datetime.now() user = User(username='test' , email='test@example.com') class UserSerializer(dt.Serializer): username = dt.StrField(max_length=50) email = dt.EmailField() created = dt.DateTimeField() class Profile : def __init__(self, age=25): self.age = age self.user = user profile = Profile() class ProfileSerializer(dt.Serializer): age = dt.IntField() user = UserSerializer() serializer = ProfileSerializer(profile) serializer.data # {'age' : 25 , 'user' : {'username': 'test', 'email': 'test@example.com', 'created': '2021-11-04T22:49:01.981127Z'}}
Filtering Output
drf-turbo provides option to enclude or exclude fields from serializer using only or exclude keywords.
serializer = UserSerializer(user,only=('id','username')) or serializer = ProfileSerializer(profile,exclude=('id','user__email')) or http://127.0.0.1:8000/user/?only=id,username
Required Fields
Make a field required by passing required=True. An error will be raised if the the value is missing from data during Deserializing.
For example:
class UserSerializer(dt.Serializer): username = dt.StrField(required=True,error_messages={"required":"no username"})
Specifying Defaults
It will be used for the field if no input value is supplied.
For example:
from datetime import datetime class UserSerializer(dt.Serializer): birthdate = dt.DateTimeField(default=datetime(2021, 11, 05))
ModelSerializer
Mapping serializer to Django model definitions.
Features :
- It will automatically generate a set of fields for you, based on the model.
- It will automatically generate validators for the serializer.
- It includes simple default implementations of .create() and .update().
class UserSerializer(dt.ModelSerializer): class Meta : model = User fields = ('id','username','email')
You can also set the fields attribute to the special value __all__ to indicate that all fields in the model should be used.
For example:
class UserSerializer(dt.ModelSerializer): class Meta : model = User fields = '__all__'
You can set the exclude attribute to a list of fields to be excluded from the serializer.
For example:
class UserSerializer(dt.ModelSerializer): class Meta : model = User exclude = ('email',)
Read&Write only fields
class UserSerializer(dt.ModelSerializer): class Meta: model = User fields = ('id', 'username', 'password','password_confirmation') read_only_fields = ('username') write_only_fields = ('password','password_confirmation')
Parsers
Allow only requests with JSON content, instead of the default of JSON or form data.
REST_FRAMEWORK = { 'DEFAULT_PARSER_CLASSES': [ 'drf_turbo.parsers.JSONParser', ] } or REST_FRAMEWORK = { 'DEFAULT_PARSER_CLASSES': [ 'drf_turbo.parsers.UJSONParser', ] } or REST_FRAMEWORK = { 'DEFAULT_PARSER_CLASSES': [ 'drf_turbo.parsers.ORJSONParser', ] }
NOTE: ujson must be installed to use UJSONParser.
NOTE: orjson must be installed to use ORJSONParser.
Renderers
Use JSON as the main media type.
REST_FRAMEWORK = { 'DEFAULT_RENDERERS_CLASSES': [ 'drf_turbo.renderers.JSONRenderer', ] } or REST_FRAMEWORK = { 'DEFAULT_RENDERERS_CLASSES': [ 'drf_turbo.renderers.UJSONRenderer', ] } or REST_FRAMEWORK = { 'DEFAULT_RENDERERS_CLASSES': [ 'drf_turbo.renderers.ORJSONRenderer', ] }
NOTE: ujson must be installed to use UJSONRenderer.
NOTE: orjson must be installed to use ORJSONRenderer.
Responses
An HttpResponse subclass that helps to create a JSON-encoded response. Its default Content-Type header is set to application/json.
from rest_framework.views import APIView import drf_turbo as dt class UserInfo(APIView): def get(self,request): data = {"username":"test"} return dt.JsonResponse(data,status=200) or class UserInfo(APIView): def get(self,request): data = {"username":"test"} return dt.UJSONResponse(data,status=200) or class UserInfo(APIView): def get(self,request): data = {"username":"test"} return dt.ORJSONResponse(data,status=200)
NOTE: ujson must be installed to use UJSONResponse.
NOTE: orjson must be installed to use ORJSONResponse.
Also drf-turbo provides an easy way to return a success or error response using SuccessResponse or ErrorResponse clasess.
for example :
class UserInfo(APIView): def get(self,request): data = {"username":"test"} serializer = UserSerializer(data=data) if not serializer.is_valid(): return dt.ErrorResponse(serializer.errors) # returned response : {'message':'Bad request', data : ``serializer_errros``, 'error': True} with status = 400 return dt.SuccessResponse(data) # returned response : {'message':'Success', data : {"username":"test"} , 'error': False} with status = 200
OpenApi(Swagger)
Add drf-turbo to installed apps in settings.py
INSTALLED_APPS = [ # ALL YOUR APPS 'drf_turbo', ]
and then register our openapi AutoSchema with DRF.
REST_FRAMEWORK = { # YOUR SETTINGS 'DEFAULT_SCHEMA_CLASS': 'drf_turbo.openapi.AutoSchema', }
and finally add these lines in urls.py
from django.views.generic import TemplateView from rest_framework.schemas import get_schema_view as schema_view from drf_turbo.openapi import SchemaGenerator urlpatterns = [ # YOUR PATTERNS path('openapi', schema_view( title="Your Project", description="API for all things …", version="1.0.0", generator_class=SchemaGenerator, public=True, ), name='openapi-schema'), path('docs/', TemplateView.as_view( template_name='docs.html', extra_context={'schema_url':'openapi-schema'} ), name='swagger-ui'), ]
Now go to http://127.0.0.1:8000/docs
Credits
This package was created with Cookiecutter and the audreyr/cookiecutter-pypackage project template.
History
0.1.0 (2021-11-10)
- First release on PyPI.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.