Skip to main content

An intelligent compiler tool to convert Django Rest Framework code to Django Ninja.

Project description

🤖 DRF to Django Ninja Compiler

CI License: MIT Python 3.10+

An intelligent, user-friendly compiler tool designed to automatically parse Django Rest Framework (DRF) code (serializers.py, views.py, urls.py, settings.py) and convert it into modern, fast Django Ninja equivalents (schemas.py, api.py).

Tired of manually migrating hundreds of legacy DRF endpoints? This tool automates the heavy lifting by leveraging Abstract Syntax Tree (AST) parsing to reverse-engineer your code.

CLI Demo

✨ Features

  • Pydantic Schemas: Parses DRF ModelSerializer and generates standard Ninja ModelSchema.
  • Nested Serializer Detection: Detects nested Serializer() fields (with many=True) and Meta.depth.
  • Intelligent Routing: Parses APIView, ModelViewSet, and all GenericAPIView variants (ListCreateAPIView, RetrieveUpdateDestroyAPIView, etc.).
  • @action Support: Detects custom ViewSet @action decorators and generates dedicated routes.
  • URL Wiring: Parses urls.py and generates NinjaAPI setup with router registration.
  • Auth & Permissions: Detects permission_classes and authentication_classes and maps them to Ninja equivalents.
  • Settings Migration: Parses REST_FRAMEWORK settings dict and generates a migration report (pagination, throttling, filters).
  • User Review: Automatically flags custom overrides (like SerializerMethodField or custom View methods) and injects helpful TODO comments so you know exactly what needs manual review.
  • Batch Mode: --project flag scans an entire Django app directory and auto-detects all DRF files.
  • Beautiful DX: Powered by Typer and Rich for a stunning terminal experience.
  • 47 Tests: Comprehensive test suite with CliRunner integration tests.

� Before & After

Your legacy DRF code:

# serializers.py
class OrderSerializer(serializers.ModelSerializer):
    total = serializers.SerializerMethodField()

    class Meta:
        model = Order
        fields = ['id', 'status', 'total']

    def get_total(self, obj):
        return sum(item.price for item in obj.items.all())

What the compiler generates:

# schemas.py (auto-generated)
class OrderSchema(ModelSchema):
    # ⚠️ USER REVIEW REQUIRED:
    # The compiler detected custom fields or methods in the DRF Serializer:
    #  - total
    #  - method:get_total
    # You will need to manually map these to Pydantic types or Resolve() blocks.
    class Meta:
        model = Order
        fields = ['id', 'status', 'total']

Your legacy DRF ViewSet:

# views.py
class OrderViewSet(viewsets.ModelViewSet):
    queryset = Order.objects.all()
    serializer_class = OrderSerializer

    def list(self, request): ...
    def create(self, request): ...

What the compiler generates:

# api.py (auto-generated)
@router.get('/order/', response=list[OrderSchema])
def list_order(request):
    """Automatically generated list view for OrderViewSet."""
    return Order.objects.all()

@router.post('/order/', response=OrderSchema)
def create_order(request, payload: OrderInSchema):
    """Automatically generated create view for OrderViewSet."""
    # TODO: Implement creation logic using payload.dict()
    pass

🚀 Installation

# Install from PyPI (recommended)
pip install drf-to-ninja

# Or install from source for development
git clone https://github.com/lektronik/drf-to-ninja-compiler.git
cd drf-to-ninja-compiler
python3 -m venv venv
source venv/bin/activate
pip install -e .

🛠 Usage

Simply point the compiler at your existing DRF files:

# Full migration — serializers, views, urls, and settings
drf2ninja -s myapp/serializers.py -v myapp/views.py -u myapp/urls.py --settings myapp/settings.py

# Use @api.get() syntax instead of @router.get()
drf2ninja -s myapp/serializers.py -v myapp/views.py --style api

# Preview without writing files
drf2ninja -s myapp/serializers.py --dry-run

# Write generated files to a directory
drf2ninja -s myapp/serializers.py -v myapp/views.py -o ./ninja_output/

# Scan entire Django app directory (auto-detects serializers, views, urls, settings)
drf2ninja --project myapp/
Flag Description
-s, --serializers Path to DRF serializers.py
-v, --views Path to DRF views.py
-u, --urls Path to DRF urls.py
--settings Path to Django settings.py
--style Output style: router (default) or api
--dry-run Preview output without writing files
-o, --output Directory to write generated files
-p, --project Scan a Django app directory (auto-detect all files)

📖 Step-by-Step Migration Guide

This is the recommended workflow to migrate a DRF app to Django Ninja:

Step 1: Run the Compiler

drf2ninja -s myapp/serializers.py -v myapp/views.py -u myapp/urls.py --settings myapp/settings.py -o ./ninja_output/

This generates four files in ./ninja_output/:

  • schemas.py — Pydantic schemas (replaces serializers)
  • api.py — Ninja route handlers (replaces views)
  • urls.py — NinjaAPI wiring (replaces DRF router config)
  • migration_report.py — Settings migration guide

Step 2: Handle Flagged Code

The compiler flags anything it can't fully auto-translate with a ⚠️ USER REVIEW REQUIRED comment. Here's what to do for each case:

Flagged Pattern What It Means What To Do
SerializerMethodField A computed field using get_*() Use a Resolver in your Schema
Custom validate_*() DRF field validator Use Pydantic's @field_validator decorator
perform_create() / perform_update() Custom save logic in ViewSet Move the logic into your Ninja route function body
Custom @action methods Extra ViewSet endpoints Create a separate @router.get() / @router.post() for each
permission_classes DRF permission check Use Ninja's auth= parameter or custom auth callables
authentication_classes DRF auth backend Use HttpBearer, django_auth, or HttpBasicAuth from ninja.security
DEFAULT_THROTTLE_CLASSES DRF throttling Use django-ninja-extra or custom middleware (Ninja has no built-in throttle)
DEFAULT_FILTER_BACKENDS DRF filter backends Use FilterSchema or manual query parameters in Ninja

Step 3: Wire the API

In your main urls.py, add the Ninja API:

# urls.py
from ninja_output.api import router  # or api, depending on --style

from ninja import NinjaAPI

api = NinjaAPI()
api.add_router("/", router)

urlpatterns = [
    path("api/", api.urls),
]

Step 4: Install Django Ninja

pip install django-ninja

Add "ninja" to INSTALLED_APPS in settings.py and run your project:

python manage.py runserver

Your new API documentation is automatically available at /api/docs.

Step 5: Verify and Clean Up

  • Visit /api/docs to confirm all endpoints are live
  • Run your existing test suite to catch regressions
  • Remove old DRF code once everything works
  • Uninstall DRF: pip uninstall djangorestframework

🔒 Security & Code Quality

This project uses pre-commit hooks to ensure code quality and security.

  • Formatting: black
  • Security Analysis: bandit

To set up the hooks locally:

pip install pre-commit
pre-commit install

🤝 Contributing

See CONTRIBUTING.md for setup instructions and guidelines.

pytest tests/  # Run the test suite (22 tests)

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

drf_to_ninja-0.3.1.tar.gz (21.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

drf_to_ninja-0.3.1-py3-none-any.whl (18.6 kB view details)

Uploaded Python 3

File details

Details for the file drf_to_ninja-0.3.1.tar.gz.

File metadata

  • Download URL: drf_to_ninja-0.3.1.tar.gz
  • Upload date:
  • Size: 21.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.3

File hashes

Hashes for drf_to_ninja-0.3.1.tar.gz
Algorithm Hash digest
SHA256 1a413a60b0a2fdb367b0667969a295df1bec4cc56cdb4e18b0f4e8348fdd2b76
MD5 7234b0f71e875ba9c50ac3d95eb9935c
BLAKE2b-256 a3fe2d6893b62a5e14bff16a0ead9b109f0d4dbcac68b0444e5c9ec8544cd374

See more details on using hashes here.

File details

Details for the file drf_to_ninja-0.3.1-py3-none-any.whl.

File metadata

  • Download URL: drf_to_ninja-0.3.1-py3-none-any.whl
  • Upload date:
  • Size: 18.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.3

File hashes

Hashes for drf_to_ninja-0.3.1-py3-none-any.whl
Algorithm Hash digest
SHA256 fa62dc25a75f639319b0ed5d949ce3fde17abd39c0ca1ca31b9f0f0b6965aa26
MD5 1242930ff14b6a82bb89b3cb002a14f0
BLAKE2b-256 f44d9d3c48155d2d0f0172f2c3c0901199b95401f1c3ab61cb32cd7e9ed633c8

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page