Use when building Django REST APIs with TurboDRF - model Meta configuration, role-based and field-level permissions, multi-tenant predicates, router wiring, management commands, settings, or troubleshooting
Pro scans all 5 files and shows the line behind each finding
Scanned 10/2/2026
npx -y skills add CodeAtCode/oss-ai-skills --skill turbodrf --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Turbodrf?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/codeatcode-turbodrf)More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.
---
name: turbodrf
description: Use when building Django REST APIs with TurboDRF - model Meta configuration, role-based and field-level permissions, multi-tenant predicates, router wiring, management commands, settings, or troubleshooting
metadata:
author: mte90
version: 2.0.0
tags:
- python
- django
- rest-api
- openapi
- serializers
- caching
---
# turbodrf
**TurboDRF** - Dead simple Django REST API generator with role-based permissions
Turn your Django models into fully-featured REST APIs with a mixin and a configuration method. Zero boilerplate.
## Overview
TurboDRF is a Django REST Framework mixin-based library that automatically generates CRUD API endpoints for your models. Unlike traditional DRF setups requiring ViewSets and serializers, TurboDRF uses a simple mixin pattern where you declare your model inherits from `TurboDRFMixin` and define a `turbodrf()` configuration method.
**Key Features:**
- Automatic CRUD endpoints from model declaration
- Role-based access control (RBAC)
- Field-level permissions
- Built-in search, filtering, ordering, and pagination
- Nested field support for relationships
- Client-side field selection (`?fields=`)
- Auto-generated API documentation (Swagger UI, ReDoc)
- Performance optimizations with compiled read path
- Security: sensitive fields deny-list, FK injection defense, startup safety gates
## Installation
### PyPI
```bash
pip install turbodrf
# Optional: faster JSON rendering (7x faster than stdlib)
pip install turbodrf[fast]
```
### GitHub
```bash
pip install git+https://github.com/AlexanderCollins/TurboDRF.git
```
### Requirements
- Python >=3.10 (tested: 3.10, 3.11, 3.12, 3.13, 3.14)
- Django >=4.2 (tested: 4.2, 5.2, 6.0)
- Django REST Framework >=3.14.0
- drf-yasg >=1.21.0, django-filter >=23.0
- Optional extras: `turbodrf[fast]` (msgspec/orjson ~7x faster), `turbodrf[allauth]` (django-allauth >=0.57.0)
Verified against TurboDRF v0.5.1 (2026-07-12).
## Quick Start
### 1. Add to `INSTALLED_APPS`
```python
# settings.py
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'rest_framework',
'django_filters',
'turbodrf',
'myapp',
]
```
### 2. Add the mixin to your model
```python
# myapp/models.py
from django.db import models
from turbodrf.mixins import TurboDRFMixin
class Book(models.Model, TurboDRFMixin):
title = models.CharField(max_length=200)
author = models.CharField(max_length=100)
price = models.DecimalField(max_digits=10, decimal_places=2)
published_date = models.DateField()
searchable_fields = ['title', 'author']
@classmethod
def turbodrf(cls):
return {
'fields': ['title', 'author', 'price', 'published_date']
}
```
### 3. Add the router
```python
# urls.py
from django.contrib import admin
from django.urls import path, include
from turbodrf.router import TurboDRFRouter
router = TurboDRFRouter()
urlpatterns = [
path('admin/', admin.site.urls),
path('api/', include(router.urls)),
]
```
### 4. Configure TurboDRF roles
```python
# settings.py
TURBODRF_ROLES = {
'admin': [
'myapp.book.read',
'myapp.book.create',
'myapp.book.update',
'myapp.book.delete',
'myapp.book.price.read',
'myapp.book.price.write',
],
'editor': [
'myapp.book.read',
'myapp.book.update',
'myapp.book.price.read',
],
'viewer': [
'myapp.book.read',
]
}
```
### 5. Extend User Model with Roles
```python
# myapp/apps.py
from django.apps import AppConfig
from django.contrib.auth import get_user_model
class MyAppConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'myapp'
def ready(self):
User = get_user_model()
def get_user_roles(self):
return [group.name for group in self.groups.all()]
if not hasattr(User, 'roles'):
User.add_to_class('roles', property(get_user_roles))
```
**Done!** You now have a full REST API at `/api/`:
```
GET /api/books/ # List all books
POST /api/books/ # Create a new book
GET /api/books/1/ # Get a specific book
PUT /api/books/1/ # Update a book
DELETE /api/books/1/ # Delete a book
```
**Query parameters:**
```
GET /api/books/?search=django # Search
GET /api/books/?author__name=Smith # Filter
GET /api/books/?ordering=-price # Order
GET /api/books/?page=2&page_size=10 # Paginate
GET /api/books/?fields=title,price # Client field selection
```
## Model Configuration
**Decision:** How do I control which fields and endpoints are exposed?
Configure your model's API surface with the `turbodrf()` classmethod. For the complete option reference, see [references/configuration.md](references/configuration.md).
### Meta Options
All options available in the `turbodrf()` classmethod:
```python
@classmethod
def turbodrf(cls):
return {
'enabled': True, # Enable/disable API (default: True)
'endpoint': 'books', # Custom endpoint name
'fields': ['title', 'author'], # Fields to expose
'public_access': False, # Allow unauthenticated GET
'lookup_field': 'pk', # URL lookup field ('pk' or 'slug')
'compiled': True, # Use compiled read path
}
```
### Fields Specification
**Decision:** Do I want all fields or a curated subset?
**All database fields:**
```python
'fields': '__all__'
```
**Specific fields (same for list and detail):**
```python
'fields': ['title', 'author', 'price']
```
**Different fields for list vs detail:**
```python
'fields': {
'list': ['title', 'author', 'price'],
'detail': ['title', 'description', 'author__email', 'price']
}
```
### Nested Fields
Access related model fields with `__` notation:
```python
'fields': [
'title',
'author__name', # ForeignKey (1 level)
'author__publisher__name', # Multi-level (2 levels)
'tags__name', # ManyToMany
]
```
FK fields are flattened (`author__name` → `author_name`). M2M fields are arrays:
```json
{
"title": "Django for APIs",
"author_name": "William Vincent",
"tags": [{"name": "Python"}, {"name": "Django"}]
}
```
Maximum nesting depth is 3 by default. Change with `TURBODRF_MAX_NESTING_DEPTH`.
### Property Fields
Model `@property` methods work in the compiled path:
```python
class Book(models.Model, TurboDRFMixin):
title = models.CharField(max_length=200)
price = models.DecimalField(max_digits=10, decimal_places=2)
@property
def display_title(self):
return self.title.upper()
@classmethod
def turbodrf(cls):
return {
'fields': ['title', 'price', 'display_title']
}
```
Properties accessing related objects won't work in compiled path — use `author__name` instead.
### List/Detail Field Separation
```python
class Book(models.Model, TurboDRFMixin):
title = models.CharField(max_length=200)
description = models.TextField()
price = models.DecimalField(max_digits=10, decimal_places=2)
@classmethod
def turbodrf(cls):
return {
'fields': {
'list': ['title', 'price'],
'detail': ['title', 'description', 'price']
}
}
```
## Documentation
Auto-generated Swagger UI and ReDoc:
- Swagger UI: `/api/swagger/`
- ReDoc: `/api/redoc/`
Disable in production:
```python
TURBODRF_ENABLE_DOCS = False
```
## Management Commands
**Decision:** How do I validate my configuration and debug issues?
```bash
# Validate configuration
python manage.py turbodrf_check
# Expected healthy output:
# "✓ All models declared with turbodrf()"
# "✓ Tenancy gates passed"
# "✓ No unsafe FK/M2M traversals detected"
# "Configuration valid."
# Expected misconfiguration output:
# "✗ Model 'MyModel' missing tenant_field or visibility declaration"
# "✗ Unsafe M2M path detected: Book.tags -> Tag.secret_data"
# "Configuration invalid. Fix errors before deployment."
# Performance benchmark
python manage.py turbodrf_benchmark
# Expected output:
# "Compiled path: 0.003s per request"
# "Serializer path: 0.021s per request"
# "Speedup: 7x"
# Explain query execution
python manage.py turbodrf_explain --model Book --query "search=django"
# Expected output:
# "Query: SELECT ... FROM books_book"
# "Tenant filter: workspace_id = 42"
# "Predicate: (owner_id = 7) OR (workspace_id IN (SELECT id FROM workspace_members ...))"
# "Fields projected: ['title', 'author__name', 'price']"
```
## Integrations
TurboDRF ships optional, experimental integrations (all settings-gated):
- **Sentry** — security-event breadcrumbs
- **Keycloak** — role mapping (`STRICT_ROLES=True` default)
- **django-allauth** — group→role mapping (`pip install turbodrf[allauth]`)
- **drf-api-tracking** — request logging
Fast JSON: `pip install turbodrf[fast]` adds msgspec (~7x faster serialization).
## AI Agent Guidance
**Decision:** What rules must I follow when generating TurboDRF code?
### Startup-Gate Kill-Switches
Never disable safety gates in production. Each gate has a kill-switch for emergencies only:
- `TURBODRF_REQUIRE_TENANCY=False` — allows models without tenant/visibility declaration
- `TURBODRF_ALLOW_UNSAFE_COMPILED_FK=True` — bypasses FK annotation safety
- `TURBODRF_ALLOW_UNSAFE_COMPILED_M2M=True` — bypasses M2M traversal safety
- `TURBODRF_ALLOW_UNSAFE_FILTER_TRAVERSAL=True` — allows filter join leaks
- `TURBODRF_ALLOW_UNSAFE_CUSTOM_WRITE=True` — allows custom predicates without write validators
- `TURBODRF_ALLOW_UNKNOWN_PERMISSIONS=True` — disables typo checking
### Tenant-Scoping Invariants
- **Prohibition:** Never write `Either(Tenant('workspace'), Owner('owner'))` — the tenant boundary must not be OR-able away. Use `visibility: [Tenant('workspace'), Either(Owner('owner'), Members('shared_with'))]` instead.
- **Mandatory:** Every shared-tenant model must declare `tenant_field`, `visibility`, or `tenancy: 'shared'`.
- **Read-only predicates:** `Members()` and `Group()` raise `NotImplementedError` on writes.
### Predicate Vocabulary Contract
When generating row-level access rules, use only these primitives from `turbodrf.predicates`:
- `Tenant(field)` — mandatory tenant boundary
- `Owner(field)` — row belongs to request.user
- `Members(field)` — M2M contains user (read-only)
- `Group(field)` — group field matches user's group (read-only)
- `Either(left, right)` — logical OR
- `Conditional(q_func, write_validator=...)` — custom with mandatory write validator
- `Custom(q_func, write_validator=...)` — fully custom with mandatory write validator
### Cache API
After bulk permission changes, call `invalidate_user_permissions(user)` to clear the permission cache.
## Best Practices
### 1. Use Meta Options
Define fields explicitly rather than `__all__` for better control.
### 2. Validate Input
Use Django's form validation or custom validators:
```python
def validate_title(value):
if Book.objects.filter(title=value).exclude(pk=self.instance.pk).exists():
raise serializers.ValidationError("Title already exists")
return value
```
### 3. Use Permissions
Restrict access appropriately:
```python
TURBODRF_ROLES = {
'public': ['myapp.book.read'],
'staff': [
'myapp.book.read',
'myapp.book.create',
'myapp.book.update',
'myapp.book.delete',
],
}
```
### 4. Filter Usage
Users can only filter on fields they have read permission for.
### 5. Secure Sensitive Data
Always include sensitive fields in the deny-list:
```python
TURBODRF_SENSITIVE_FIELDS = [
'password', 'token', 'api_key', 'secret_key',
]
```
## Deep Dives
The following reference documents are loaded on demand from `references/`:
- **references/configuration.md** — Complete Meta options, settings reference, startup safety gates
- **references/permissions-tenancy.md** — Role-based permissions, field-level access, multi-tenant predicates, row-level scoping
- **references/security-settings.md** — Security gates, fail-closed design, troubleshooting
- **references/examples.md** — Complete CRUD API examples with nested relationships
## References
- **GitHub Repository**: https://github.com/AlexanderCollins/TurboDRF
- **PyPI Package**: https://pypi.org/project/turbodrf/
- **Documentation**: https://github.com/AlexanderCollins/TurboDRF/tree/main/docs
- [Configuration](https://github.com/AlexanderCollins/TurboDRF/blob/main/docs/configuration.md)
- [Permissions](https://github.com/AlexanderCollins/TurboDRF/blob/main/docs/permissions.md)
- [Tenancy & row-level access](https://github.com/AlexanderCollins/TurboDRF/blob/main/docs/tenancy.md)
- [Performance](https://github.com/AlexanderCollins/TurboDRF/blob/main/docs/performance.md)
- [Filtering & Search](https://github.com/AlexanderCollins/TurboDRF/blob/main/docs/filtering.md)
- [Integrations](https://github.com/AlexanderCollins/TurboDRF/blob/main/docs/integrations.md)
- [Security](https://github.com/AlexanderCollins/TurboDRF/blob/main/docs/security.md)
- [Management Commands](https://github.com/AlexanderCollins/TurboDRF/blob/main/docs/commands.md)
- [Settings Reference](https://github.com/AlexanderCollins/TurboDRF/blob/main/docs/settings_reference.md)
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!