惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
云风的 BLOG
云风的 BLOG
aimingoo的专栏
aimingoo的专栏
Vercel News
Vercel News
T
The Blog of Author Tim Ferriss
F
Full Disclosure
A
About on SuperTechFans
C
Check Point Blog
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
量子位
Know Your Adversary
Know Your Adversary
K
Kaspersky official blog
L
LINUX DO - 热门话题
Recorded Future
Recorded Future
C
Cisco Blogs
M
MIT News - Artificial intelligence
T
Tenable Blog
G
GRAHAM CLULEY
月光博客
月光博客
Recent Announcements
Recent Announcements
V
Visual Studio Blog
IT之家
IT之家
T
The Exploit Database - CXSecurity.com
The GitHub Blog
The GitHub Blog
T
Threat Research - Cisco Blogs
D
DataBreaches.Net
P
Privacy International News Feed
P
Proofpoint News Feed
I
Intezer
博客园 - 叶小钗
C
CXSECURITY Database RSS Feed - CXSecurity.com
The Hacker News
The Hacker News
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
博客园 - Franky
SecWiki News
SecWiki News
宝玉的分享
宝玉的分享
P
Palo Alto Networks Blog
Last Week in AI
Last Week in AI
小众软件
小众软件
Hacker News - Newest:
Hacker News - Newest: "LLM"
O
OpenAI News
N
News and Events Feed by Topic
Microsoft Security Blog
Microsoft Security Blog
Security Archives - TechRepublic
Security Archives - TechRepublic
N
News and Events Feed by Topic
The Cloudflare Blog
Spread Privacy
Spread Privacy
酷 壳 – CoolShell
酷 壳 – CoolShell
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
B
Blog RSS Feed

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant Common SOC 2 Failures (Real World) Stop Vibe-Checking Your AI App: A Practical Guide to Evals How to Use SonarQube and SonarScanner Locally to Level Up Your Code Quality Your Next To-Do App Is Dead — I Replaced Mine with an OpenClaw AI Sign a Nostr event in 60 lines of Python using coincurve — no nostr-sdk, no nbxplorer, no rust toolchain ITGC Audit Explained Like You’re in Big 4 Patch Tuesday abril 2026: Microsoft parcha 163 vulnerabilidades y un zero-day en SharePoint Stop scraping everything: a better way to track competitor price changes Listing on MCPize + the Official MCP Registry while routing payments OUTSIDE the marketplace — how I kept 100% of my x402 revenue Building an AI-Powered Risk Intelligence System Using Serverless Architecture Why We Ripped Function Overloading Out of Our AI Toolchain Testing AI-Generated Code: How to Actually Know If It Works SaaS Churn Is Killing Your Business. Here Is What to Do About It (Without a Support Team) The Speed of AI Is No Longer Linear - And Self-Improving Models Are Why How to Implement RBAC for MCP Tools: A Practical Guide for Engineering Teams From Standard Quote to Persuasive Proposal: AI Automation for Arborists I built a CLI that scaffolds complete multi-tenant SaaS apps Axios CVE-2025–62718: The Silent SSRF Bug That Could Be Hiding in Your Node.js App Right Now The dashboard that ended our friendship Data Pipelines Explained Simply (and How to Build Them with Python) The Hidden Cost of AI Systems Nobody Talks About. undefined vs undeclared, and how typeof behaves Switching from file-based jobs to NATS/Kafka in Rust without changing code io_uring Adventures: Rust Servers That Love Syscalls Why Agentic AI is Killing the Traditional Database The POUR principles of web accessibility for developers and designers Quantum Neural Network 3D — A Deep Dive into Interactive WebGL Visualization How To Install Caveman In Codex On macOS And Windows Automation Pipeline Reliability: Why Your Workflow Breaks When Nobody Is Watching I Built an 'Open World' AI Coding Agent — It Works From ANY Folder From Freelancing to Product: A Tech Service Company's SaaS Transformation China's AI Giants: Adding Tencent Hunyuan & ByteDance Doubao to AI University (74 Providers) On the Vibe Coders and Their Lies clerk: Auto-Summarize Your Claude Code Sessions AI Weekly — 2026/04/10–04/17 | The Model Lockdown Is Here, but the Toolchain Is the Real Battleground AI 週報 — 2026/04/10–2026/04/17 模型封鎖潮來了,但工具鏈才是真戰場 Maybe this is how Open-Source apps are born... 🚀 Fine-Tune LLMs with LoRA and QLoRA: 2026 Guide tRPC v11 + Next.js App Router: End-to-End Type Safety Without the Boilerplate ShadCN UI in 2026: Why I Stopped Installing Component Libraries and Started Owning My Components SaaS Billing in React Server Components: Stripe + Supabase Without a Single `useEffect` Join our DEV Weekend Challenge — $1,000 in Prizes Across TEN winners! Submissions Due April 20 at 6:59 AM UTC. Implementing FSRS Spaced Repetition in Flutter + Supabase — Adding Memory Science to an AI Learning App "I Texted My Localhost From the Train — Claude Code Fixed the Bug Before I Got Home" I Built a Sales Prep AI and It Went Deeper Than Expected Design to Code #2: One JSON, Eleven Outputs Solving the 100M-Row Problem: A Summary Table Pattern for High-Volume Push Notification Logs Flutter Web With Wasm: What Actually Changes For Developers I Built 50 Royalty-Free Soundtracks for My Side Project in a Weekend Using AI Music Generation The Vibe Coding Security Checklist: 7 Things to Check Before You Ship Stop Letting Googlebot Guess Fix Your React App's SEO Right Desconstruindo o Streaming do LinkedIn: Como Criar um Engine de Extração de Vídeo de Alta Performance com HLS e FFmpeg (EDA Part-1) EDA (Exploratory Data Analysis) Explained With Real Life — Why Looking at Your Data Is the Most Important Step in Machine Learning Brand Relationship Management at Scale: Our 4-Touch Outreach System for 200+ Brands Why String.fromEnvironment() Might Return an Empty String in Dart JGuardrails 1.0.0 — Hardening Java LLM Apps Against Jailbreaks, Toxicity, and Prompt Injection Plan and Schedule a Full Week of Threads Content From One Claude Conversation Coding Cat Oran Ep3, Five Tables Changed Everything Updated: BFF Pattern I'm done watching freelancers get buried by 200 proposals. So I'm building the alternative. This is my first post BFS Algorithm in Java Step by Step Tutorial with Examples Tracking LLM Pricing Monthly: An Open Dataset for 22 AI Models How We Measure Content ROI on a Comparison Site: Revenue Attribution Without Perfect Data Introducing Nova AI Ops: The AI-Native Operating System for SRE Teams I built a free desktop video downloader for Windows — Grabbit How Talkie OCR Helps Vision-Impaired & Dyslexic Users Read the World Around Them VRCFaceTracking安装和iPhone面捕配置教程,有bug Even CrowdStrike Can't See Your Agents The Automation Gold Rush: What n8n Workflows and Claude Are Opening Up for Developers Right Now
Django Ninja: The Sweet Spot Between Django's Simplicity and FastAPI's Power
Ja'far Khakpour · 2026-06-03 · via DEV Community

My first experience using Django REST Framework (DRF) in a project was almost a decade ago. I've defeneded DRF philosophy it in code reviews, taught it to juniors, and built production systems that still run today. But in recent years, after trying FastAPI in different projects, I started feeling bored. Not of Django. I still love Django. I felt it from the verbose boilerplate, layers of abstraction that solved problems I no longer had amde me ask myself if I need this much complexity in one place?

Then I found Django Ninja. And after two years of using it in production, I finally understand what I was missing.

This post isn't about "DRF is dead" — it's not. It's about understanding where each tool shines, and why Ninja has become my default for most new projects.

Let me walk you through the landscape honestly.


1. Django in 2026

Let's start with something we can all agree on: Django is still fantastic. Here's why I still reach for Django first:

  • "Batteries included" actually matters. Authentication, admin interface, sessions, CSRF protection, security middleware — it's all there, tested, and working. No stitching together 14 Flask extensions or FastAPI plugins.

  • The admin interface is a superpower. For internal tools, MVP dashboards, or giving non-technical staff data access, nothing else comes close (I know there are alternatives for other frameworks, but still none feels like Django's Admin Panel).

  • The ORM is genuinely productive. To be honest, I love SQLAlchemy, and I hate some weird behavior of Django ORM, but no one can argue how well it integrates with the whole framework.

  • The ecosystem is enormous. I can put here a never ending list of great apps and modules for anything you need in your project.

But Django's built-in API tooling is not good.

If you've ever tried to build a real API using only JsonResponse and manual request parsing, you know the pain:

  • Manual validation everywhere
  • No automatic documentation
  • Routing feels repetitive
  • Error handling is ad hoc

That's why we reached for DRF in the first place. But DRF was built in a different age.


2. DRF: A Decade-Old Masterpiece Showing Its Age

Let me be clear: DRF is not bad code. It's brilliant code written for a different world.

The Era DRF Was Built For (2011–2015)

Back then, the hot API trends were:

  • RESTful purity — Hypermedia as the engine of application state (HATEOAS), resource-oriented design, proper HTTP verbs for everything
  • Hypermedia APIsHyperlinkedRelatedField was a feature, not a footnote
  • Browsable API — inspired by Django admin, it was revolutionary for debugging
  • Class-based views — because function-based views were "too simple" those days!
  • XML support — yes, that's how old we're talking.

What DRF Did Right

  • Standardized REST APIs on Django — before DRF, everyone rolled their own. It standardized a lot of concepts in Dajngo ecosystem.
  • Built a mature ecosystemdjango-rest-auth, drf-spectacular, drf-nested-routers, etc.
  • Introduced serializers — which, love them or hate them, were a solid abstraction for their time
  • Gave us ViewSets + routers — made CRUD APIs almost automatic

What DRF Struggles With Today

  • No official async support — and no announced plans. Django added async in version 3.0 (2019), then 3.1, then 4.0, etc. But DRF? Still sync-only. The workarounds are fragile.

  • OpenAPI docs require third-party packagesdrf-yasg (not very active at maintenance), drf-spectacular (good but still extra work). No built-in solution.

  • Serializers are slow and verbose — pure Python, lots of reflection, and writing Meta classes for every model gets tedious.

  • ViewSets + routers are magical — great when they work, a nightmare when you need to debug why your destroy action isn't honoring permissions.

  • The browsable API is less useful now — frontends are separate. Postman, Swagger UI, and generated clients are the modern workflow.

DRF is like a well-maintained 2015 luxury car. Comfortable, known, reliable. Great engine, but terrible gas mileage compared to modern hybrids. Steering system is fascinating, but the navigation is outdated.

That doesn't mean throw it away. But maybe stop buying new ones.


3. FastAPI: The Shiny New Toy That Makes You Question Everything

Around 2018, FastAPI exploded onto the scene. And for good reason.

What FastAPI got right:

  • Async by default — before Django even had solid async support
  • Pydantic validation — type hints that actually validated your data at runtime
  • Automatic OpenAPI docs — Swagger UI and ReDoc with zero configuration
  • Incredible performance — as fast as Node or Go for many workloads
  • Dependency injection — an elegant, testable, and intuitive design pattern

I built several microservices with FastAPI. I enjoyed every minute of it.

But here's what nobody tells you about leaving Django for FastAPI:

  • Batteries not included. You reach for SQLAlchemy — which is excellent, but different. And now you're also reaching for Alembic (migrations), and something for admin, and something for auth, and something for...

  • No built-in authentication system. You'll piece together OAuth2, JWT, sessions, or reach for fastapi-users (good library, but not Django's django.contrib.auth).

  • You're building half of Django yourself. That's fine for a small microservice. For a maintained large application? That's technical debt disguised as "lightweight."

The honest take: FastAPI is fantastic for microservices, APIs that need pure async, or greenfield projects where you don't need Django's ecosystem. But if you already have Django — or you love Django's "batteries" — leaving hurts.

What if you could have FastAPI's ergonomics inside Django world? Enter Django Ninja.


4. Django Ninja: What It Is and Why It Matters

Django Ninja was created around 2020 — explicitly inspired by FastAPI but built for Django, not against it.

The core idea is to keep Django's ORM, admin, auth, and ecosystem. Replace only the API layer with something modern.

You have Pydantic validation in APIs, type hints everywhere, native async support, automatic OpenAPI docs and other modern features.

Key distinction I missed for too long: Django Ninja alone is not a REST framework. It's a modern HTTP layer. You add REST conventions on top if you want them (more on that in next sections).

Now let me explain why each feature matters in practice.


5. Let's Dive Deeper Into Key Features

5.1 Framework Speed (Request/Overhead)

Django Ninja isn't as fast as FastAPI, but it's meaningfully faster than DRF — and for most Django projects, that's the comparison that matters. DRF's request/response cycle passes through parsers, renderers, and content negotiators on every request, and its serializers do heavy runtime introspection in pure Python. Ninja skips most of that by default, and hands validation to Pydantic v2, whose core is written in Rust. Your database is still your real bottleneck, but lower validation overhead means better latency and a framework that doesn't fight you when you need async.

  • DRF's serializers do a lot of work — field introspection, validation, object transformation
  • DRF's request/response cycle passes through multiple layers (parsers, renderers, negotiators)
  • Ninja does less by default — you opt into complexity

5.2 Pydantic vs. DRF Serializers: Speed + Syntax

Speed first:

Pydantic v2's validation core is written in Rust. DRF serializers are pure Python with heavy use of getattr, hasattr, and runtime introspection. The result is better performance for validation, which is even higher for complex nested validation.

This matters when you're validating arrays of objects or request bodies with 20+ fields.

And the syntax: the real win for developer happiness. DRF serializers are much more verbose compared to Pydantic scheams.

What I actually care about: Less code. Fewer files to jump between. Validation that lives with the schema. Autocomplete everywhere because Pydantic uses standard Python types. It is much easier to get how Pydantic works compared to DRF serializers and steep leanirng curve of this tool.


5.3 Where Django Ninja Sits on the Abstraction Spectrum

Think of it as a an spectrum: plain Django with JsonResponse at one end, full DRF with ViewSets and routers at the other, and Django + Ninja sitting cleanly in the middle. Most APIs don't actually need a full REST framework — they need validation, docs, and async. That's Ninja on its own, with no Meta classes, no serializer/view split, no router ceremony. The mistake I made for years was reaching for DRF by default and carrying all that weight before knowing if I needed it.

I used to reach for DRF by default. Now I ask: "Do I actually need ViewSets? Browsable API? Hyperlinked relationships?" 80% of the time, the answer is no.


5.4 Ninja + CRUD / Extra: When You Want RESTful Convenience (This Is the Real DRF Alternative)

If you genuinely want DRF-style RESTful conventions (ModelViewSet, automatic CRUD, router registration), don't build it yourself. Use these add-ons:

Django Ninja CRUD

  • ModelViewSet-like functionality on top of Ninja
  • Auto-generates endpoints: GET /items, POST /items, GET /items/{id}, PUT /items/{id}, DELETE /items/{id}
  • Pydantic schemas auto-generated from your Django models
  • Permission control per action (similar to DRF's permission_classes)

Django Ninja Extra (My Preference)

  • Class-based controllers
  • Service layer injection — similar to FastAPI's dependency injection, but inside Django
  • Separating API handling codes from business logic using service based controllers and dependency injection
  • Advanced pagination, filtering, throttling out of the box
  • OpenAPI extended features
  • What DRF doesn't have: Native async, service-level DI, cleaner separation between HTTP layer and business logic

In DRF, business logic tends to bleed into views — one database call becomes a caching layer becomes an external API call, and suddenly your view is untestable. Ninja Extra's DI lets you put that logic in a service class and inject it into your controller, so the controller handles HTTP and nothing else. In tests you swap the service for a mock; in production you swap it for one that hits a cache first — the controller never changes. It's the clean separation DRF gestures toward but never quite delivers.

So the real comparison is: DRF vs. Ninja CRUD/Extra for RESTful conventions. Vanilla Ninja is a different (often better) choice for non-RESTful APIs.


6. Progressive Adoption: Ninja's Undervalued Superpower

Most "better" tools force a choice: rewrite everything or stay stuck.

Django Ninja gives you a third path: coexistence and gradual migration.

Real Example From My Last Project

We had a 30,000-line DRF codebase. Full rewrite? Impossible. Here's what we did in a large project:

1) Install Ninja alongside DRF (no breaking changes):

# urls.py
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('api/', include('old_drf_urls')),      # Existing DRF endpoints
    path('ninja/api/', include('myapp.ninja_router')), # New Ninja based endpoints with a ninja/ prefix on paths
]

Enter fullscreen mode Exit fullscreen mode

2) All new features written in Ninja:

  • Same authentication (request.user works)
  • Same models (Django ORM unchanged)
  • Same middleware (CORS, security, sessions — all work)
  • Same testing tools (django.test.Client, force_login)

Result: Zero friction. The team learned Ninja on real tasks, not tutorials.

3) Gradually migrate high-traffic DRF endpoints:

  • Pick one endpoint (e.g., GET /api/v1/users/profile)
  • Write Ninja version with identical response structure
  • Deploy both versions
  • Update client application to use Ninja URL
  • Remove DRF version after 2 weeks of stability

End result after 2 months: 80% of traffic served by Ninja, DRF endpoints still running but deprecated. No downtime. No big bang. No anxious weekends debugging a full rewrite.

This Works So Seamlessly, you don't need to migrate ORM, migrations, auth handlers, tests or admin panel. You also don't need to touch your deployment plan!

Ninja is not a migration — it's an upgrade path that respects your existing investment.


7. Conclusion: My 2026 Rule of Thumb

After two years of using Ninja in production, here's my honest decision table:

Scenario My Choice
New Django project, simple API (most cases) Django Ninja (vanilla)
New Django project, CRUD-heavy (admin panel, internal tool) Django Ninja + CRUD
New Django project, complex REST + service layer Django Ninja Extra
Existing DRF project, adding new endpoints Add Ninja alongside, don't touch old code
Existing DRF project with budget to modernize Incremental migration to Ninja (endpoint by endpoint)
Team deeply tied to DRF patterns, no willingness to change Stay with DRF — tooling isn't worth team friction
Non-Django project (microservice, pure async, no admin needed) FastAPI or Litestar
Legacy DRF project with HATEOAS or browsable API requirements DRF (Ninja doesn't have these by default)

The Bottom Line

Django Ninja respects Django. It doesn't ask you to leave the Dajngo ecosystem. It just asks you to write better APIs with less frustration.

And the progressive adoption path means you can start today — on one endpoint — without any risk.

I'm not saying drop DRF from your projects. It's a really wonderful and robust framework. I'm saying: next time you start a new endpoint, try Ninja. See how it feels.

Most of my colleagues didn't want to switch. Now they refuse to go back.


Have you tried Django Ninja? Still on DRF? Made the jump to FastAPI and never looked back? Let me know in the comments — I genuinely enjoy hearing how other teams are solving these same problems.

And if you found this useful, consider sharing it with someone who's still writing ModelSerializer and wondering if there's a better way.