Skip to content

Latest commit

 

History

History
571 lines (439 loc) · 12.7 KB

File metadata and controls

571 lines (439 loc) · 12.7 KB
name turbadrf
description TurboDRF - fast Django REST framework with automatic OpenAPI, serializers, views, routers, and caching
metadata
author version tags
mte90
1.0.0
python
django
rest-api
openapi
fast

TurboDRF

Fast Django REST framework.

Overview

TurboDRF is a high-performance REST framework for Django that provides automatic OpenAPI documentation, powerful serializers, views, routers, and built-in caching.

Key Features:

  • Automatic OpenAPI/Swagger documentation
  • Powerful serializers with validation
  • ViewSets and GenericViews
  • Automatic router generation
  • Built-in caching support
  • JWT authentication
  • Rate limiting

Installation

pip install turbodrframework

# With caching support
pip install turbodrframework[cache]

# With async support
pip install turbodrframework[async]

Quick Start

Basic Setup

# settings.py
INSTALLED_APPS = [
    'rest_framework',
    'turbodrframework',
    'myapp',
]

TURBODRF = {
    'OPENAPI_ENABLED': True,
    'CACHE_ENABLED': True,
}

Minimal ViewSet

from turbodrframework import ModelViewSet, Serializer

class UserSerializer(Serializer):
    class Meta:
        model = User
        fields = ['id', 'username', 'email']

class UserViewSet(ModelViewSet):
    serializer_class = UserSerializer
    queryset = User.objects.all()
    lookup_field = 'pk'

URLs

from turbodrframework import routers
from myapp.views import UserViewSet

router = routers.DefaultRouter()
router.register(r'users', UserViewSet)

urlpatterns = router.urls

Serializers

ModelSerializer

from turbodrframework import Serializer, ModelSerializer
from django.contrib.auth.models import User

class UserSerializer(ModelSerializer):
    class Meta:
        model = User
        fields = ['id', 'username', 'email', 'first_name', 'last_name']
        read_only_fields = ['id']

class UserDetailSerializer(ModelSerializer):
    class Meta:
        model = User
        fields = '__all__'

Field Validation

class UserRegistrationSerializer(Serializer):
    username = serializers.CharField(min_length=3, max_length=50)
    email = serializers.EmailField()
    password = serializers.CharField(write_only=True, min_length=8)
    confirm_password = serializers.CharField(write_only=True)

    def validate(self, data):
        if data['password'] != data['confirm_password']:
            raise serializers.ValidationError("Passwords don't match")
        return data

    def create(self, validated_data):
        validated_data.pop('confirm_password')
        user = User.objects.create_user(**validated_data)
        return user

Nested Serializers

class CommentSerializer(Serializer):
    id = serializers.IntegerField()
    text = serializers.CharField()
    author = serializers.StringRelatedField()

class PostSerializer(Serializer):
    id = serializers.IntegerField()
    title = serializers.CharField()
    comments = CommentSerializer(many=True, read_only=True)
    author = UserSerializer(read_only=True)

Views

ModelViewSet

from turbodrframework import ModelViewSet
from myapp.models import Article
from myapp.serializers import ArticleSerializer

class ArticleViewSet(ModelViewSet):
    serializer_class = ArticleSerializer
    queryset = Article.objects.all()
    lookup_field = 'slug'
    filterset_fields = ['category', 'status']
    search_fields = ['title', 'content']
    ordering_fields = ['created_at', 'updated_at']
    ordering = ['-created_at']

Custom Actions

class ArticleViewSet(ModelViewSet):
    serializer_class = ArticleSerializer
    queryset = Article.objects.all()

    @action(detail=True, methods=['post'])
    def publish(self, request, pk=None):
        article = self.get_object()
        article.status = 'published'
        article.save()
        return Response({'status': 'published'})

    @action(detail=False, methods=['get'])
    def published(self, request):
        articles = self.queryset.filter(status='published')
        serializer = self.get_serializer(articles, many=True)
        return Response(serializer.data)

Generic Views

from turbodrframework import (
    ListAPIView,
    CreateAPIView,
    RetrieveAPIView,
    UpdateAPIView,
    DestroyAPIView,
    ListCreateAPIView,
    RetrieveUpdateAPIView,
)

class UserListCreateView(ListCreateAPIView):
    serializer_class = UserSerializer
    queryset = User.objects.all()

class UserDetailView(RetrieveUpdateDestroyAPIView):
    serializer_class = UserSerializer
    queryset = User.objects.all()
    lookup_field = 'pk'

Authentication

JWT Authentication

# settings.py
TURBODRF = {
    'AUTH_CLASS': 'turbodrframework.authentication.JWTAuthentication',
    'JWT_SECRET_KEY': 'your-secret-key',
    'JWT_ALGORITHM': 'HS256',
    'JWT_EXPIRATION': 3600,  # seconds
}

# views.py
from turbodrframework import ModelViewSet
from turbodrframework.permissions import IsAuthenticated

class SecureViewSet(ModelViewSet):
    permission_classes = [IsAuthenticated]
    queryset = SecureModel.objects.all()

Token Authentication

# settings.py
TURBODRF = {
    'AUTH_CLASS': 'turbodrframework.authentication.TokenAuthentication',
}

# urls.py
from turbodrframework.authentication import obtain_token

urlpatterns = [
    path('api/token/', obtain_token),
]

Custom Authentication

from turbodrframework.authentication import BaseAuthentication

class APIKeyAuthentication(BaseAuthentication):
    def authenticate(self, request):
        api_key = request.headers.get('X-API-Key')
        if not api_key:
            return None
        
        try:
            user = APIKey.objects.get(key=api_key).user
            return (user, None)
        except APIKey.DoesNotExist:
            return None

Permissions

Built-in Permissions

from turbodrframework.permissions import (
    AllowAny,
    IsAuthenticated,
    IsAdminUser,
    IsAuthenticatedOrReadOnly,
)

class ArticleViewSet(ModelViewSet):
    permission_classes = [IsAuthenticatedOrReadOnly]

Custom Permissions

from rest_framework import permissions

class IsOwnerOrReadOnly(permissions.BasePermission):
    def has_object_permission(self, request, view, obj):
        if request.method in permissions.SAFE_METHODS:
            return True
        return obj.owner == request.user

class ArticleViewSet(ModelViewSet):
    permission_classes = [IsAuthenticatedOrReadOnly, IsOwnerOrReadOnly]

Caching

Cache Configuration

# settings.py
TURBODRF = {
    'CACHE_ENABLED': True,
    'CACHE_CLASS': 'turbodrframework.cache.RedisCache',
    'CACHE_CONFIG': {
        'LOCATION': 'redis://127.0.0.1:6379/0',
    },
    'CACHE_TIMEOUT': 300,  # 5 minutes
}

# Or use default cache
TURBODRF = {
    'CACHE_ENABLED': True,
    'CACHE_CLASS': 'django.core.cache.backends.locmem.LocMemCache',
}

View Caching

class ArticleViewSet(ModelViewSet):
    serializer_class = ArticleSerializer
    queryset = Article.objects.all()
    
    @cache_response(timeout=60)
    def list(self, request):
        # This view will be cached for 60 seconds
        return super().list(request)
    
    @cache_response(timeout=300)
    def retrieve(self, request, pk=None):
        # Individual article cached for 5 minutes
        return super().retrieve(request, pk)

Cache Invalidation

from turbodrframework.cache import invalidate_cache

# Invalidate specific view cache
invalidate_cache('ArticleViewSet', 'list')

# Invalidate all caches
invalidate_cache('ArticleViewSet')

# Invalidate by key
invalidate_cache('ArticleViewSet:list', user_id=1)

Filtering

QuerySet Filtering

class ArticleViewSet(ModelViewSet):
    serializer_class = ArticleSerializer
    queryset = Article.objects.all()
    filterset_fields = ['category', 'status', 'author']
    search_fields = ['title', 'content', 'tags']

Custom Filtering

from turbodrframework.filters import FilterSet

class ArticleFilter(FilterSet):
    category = filters.CharFilter(field_name='category__slug')
    published_after = filters.DateTimeFilter(field_name='created_at', lookup_expr='gte')
    author_username = filters.CharFilter(field_name='author__username')

    class Meta:
        model = Article
        fields = ['category', 'status', 'published_after']

class ArticleViewSet(ModelViewSet):
    serializer_class = ArticleSerializer
    queryset = Article.objects.all()
    filterset_class = ArticleFilter

Pagination

Default Pagination

# settings.py
TURBODRF = {
    'PAGINATION_CLASS': 'turbodrframework.pagination.PageNumberPagination',
    'PAGE_SIZE': 20,
}

Custom Pagination

class CustomPagination(pagination.PageNumberPagination):
    page_size = 50
    page_query_param = 'page'
    page_size_query_param = 'page_size'
    max_page_size = 100

class ArticleViewSet(ModelViewSet):
    serializer_class = ArticleSerializer
    queryset = Article.objects.all()
    pagination_class = CustomPagination

Cursor Pagination

class ArticleViewSet(ModelViewSet):
    serializer_class = ArticleSerializer
    queryset = Article.objects.all().order_by('id')
    pagination_class = pagination.CursorPagination
    page_size = 100

OpenAPI Documentation

Auto-Generated Docs

# settings.py
TURBODRF = {
    'OPENAPI_ENABLED': True,
    'OPENAPI_TITLE': 'My API',
    'OPENAPI_VERSION': '1.0.0',
    'OPENAPI_DESCRIPTION': 'API documentation',
}

# URLs
from turbodrframework.docs import schema_view

urlpatterns = [
    path('docs/', schema_view),
]

Custom Schema

from turbodrframework.docs import AutoSchema

class CustomSchema(AutoSchema):
    def get_operation_id(self, path, method):
        # Custom operation ID
        return f"{method.lower()}_{path.replace('/', '_')}"

class ArticleViewSet(ModelViewSet):
    serializer_class = ArticleSerializer
    queryset = Article.objects.all()
    schema = CustomSchema()

Request/Response Examples

from turbodrframework.docs import extend_schema

class ArticleViewSet(ModelViewSet):
    serializer_class = ArticleSerializer
    queryset = Article.objects.all()

    @extend_schema(
        request=ArticleSerializer,
        responses={201: ArticleSerializer},
        examples=[
            {
                "title": "Example Article",
                "content": "Article content here",
            }
        ]
    )
    def create(self, request, *args, **kwargs):
        return super().create(request, *args, **kwargs)

Rate Limiting

Configuration

# settings.py
TURBODRF = {
    'RATE_LIMIT_ENABLED': True,
    'RATE_LIMIT_CLASS': 'turbodrframework.throttling.SimpleRateThrottle',
    'DEFAULT_RATE': '100/minute',
}

# View-level
class ArticleViewSet(ModelViewSet):
    throttle_classes = [UserRateThrottle]
    throttle_scope = 'articles'

Examples

Complete CRUD API

# serializers.py
from turbodrframework import ModelSerializer
from myapp.models import Article

class ArticleSerializer(ModelSerializer):
    class Meta:
        model = Article
        fields = ['id', 'title', 'content', 'author', 'created_at', 'updated_at']
        read_only_fields = ['id', 'created_at', 'updated_at']

# views.py
from turbodrframework import ModelViewSet
from myapp.models import Article
from myapp.serializers import ArticleSerializer

class ArticleViewSet(ModelViewSet):
    serializer_class = ArticleSerializer
    queryset = Article.objects.all()
    filterset_fields = ['category']
    search_fields = ['title', 'content']
    ordering_fields = ['created_at', 'title']
    
    def perform_create(self, serializer):
        serializer.save(author=self.request.user)
    
    def get_queryset(self):
        return self.queryset.filter(author=self.request.user)

# urls.py
from turbodrframework import routers
from myapp.views import ArticleViewSet

router = routers.DefaultRouter()
router.register(r'articles', ArticleViewSet)

urlpatterns = router.urls

Best Practices

1. Use Meta Options

class UserSerializer(ModelSerializer):
    class Meta:
        model = User
        fields = ['id', 'username', 'email']
        read_only_fields = ['id']

2. Validate Input

def validate_username(self, value):
    if User.objects.filter(username=value).exists():
        raise serializers.ValidationError("Username already exists")
    return value

3. Use Permissions

class ArticleViewSet(ModelViewSet):
    permission_classes = [IsAuthenticatedOrReadOnly]

References