No Boilerplate, just rapid Django API ⚡️
Write powerful Django APIs with minimal code. Djapy combines Django's robustness with modern API development practices, giving you a clean, intuitive way to build REST APIs.
@djapify
def get_user(request, user_id: int) -> UserSchema:
return User.objects.get(id=user_id)
from djapy import djapify, Schema
class UserOut(BaseModel):
id: int
username: str
is_active: bool
@djapify
def get_users(request) -> list[UserOut]:
return User.objects.filter(is_active=True)
Write Django REST APIs in pure Python. No serializers, no viewsets, no boilerplate, no external url routers - just clean, typed, and maintainable code.
- Zero Boilerplate: Build APIs with pure Python and Django
- Type Safety: Full Python type hints support
- Modern Validation: Built-in Pydantic integration
- Hyperfast Performance: Optimized for speed
- Django Compatible: Works with any Django project
- OpenAPI Support: Automatic Swagger documentation
- IDE Friendly: Full intellisense, endpoints (PyCharm) and type support
- Install Djapy
pip install djapy
- Create Your First API
from djapy import djapify, Schema
from django.contrib.auth.models import User
class UserSchema(Schema):
id: int
username: str
email: str
@djapify
def list_users(request) -> list[UserSchema]:
return User.objects.all()
@djapify
def get_user(request, user_id: int) -> {200: UserSchema, 404: str}:
try:
return User.objects.get(id=user_id)
except User.DoesNotExist:
return "User not found", 404
- Add to URLs
from django.urls import path
urlpatterns = [
path('users/', list_users),
path('users/<int:user_id>/', get_user),
]
from typing import Optional
from djapy import djapify, Schema
from djapy.pagination import paginate
class UserFilter(Schema):
search: Optional[str]
is_active: bool = True
@djapify
@paginate
def search_users(request, filters: UserFilter) -> list[Schema]:
queryset = User.objects.filter(is_active=filters.is_active)
if filters.search:
queryset = queryset.filter(username__icontains=filters.search)
return queryset
@djapify
def create_user(request, data: UserCreate, team_id: int) -> {201: UserSchema}:
# Automatic validation and parsing
return 201, User.objects.create(**data.dict())
Learn more about type system and requests, here.
@djapify
def make_payment(request, amount: float) -> {200: PaymentSchema}:
if request.user.balance < amount:
raise MessageException("Insufficient balance")
return Payment.objects.create(user=request.user, amount=amount)
More about error handling, here.
DRF Concept | Djapy Equivalent |
---|---|
ViewSets | Function-based views with @djapify |
Serializers | Pydantic models |
Permissions | Python decorators |
Filters | Query parameters |
Pagination | Built-in pagination helpers |
Visit djapy.io for comprehensive documentation.
- 📖 Documentation
- 💬 Community
- 🐛 Issue Tracker
- 📦 PyPI