Getting Started with Django: Why This 20-Year-Old Framework Is Still Worth Learning

Julia Evans explains why Django's explicit design and mature ecosystem make it ideal for personal projects.
Tech blogger Julia Evans shares why she chose Django over Rails. Django's explicit design keeps code understandable even after long periods of inactivity, while its built-in Admin backend, powerful ORM, and automatic migration system dramatically boost development efficiency. She also recommends using SQLite instead of Postgres for small websites, arguing that Django — a mature framework with 20 years of history — offers tremendous value for personal projects through its rich community resources and batteries-included philosophy.
Why Choose an "Old-School Technology" Like Django
Renowned tech blogger Julia Evans recently shared her experience learning Django. She raised a rather insightful point: learning a "boring, old" technology that's been around for over 20 years is actually an excellent experience — every problem you encounter has already been solved thousands of times, community documentation and solutions are incredibly rich, and you can focus on simply getting things done.
Background: Django's Origins and Evolution Django was born in 2003, created by the development team at the Lawrence Journal-World newspaper, and released as open source in 2005. Its original design goal was to meet the rapid iteration demands of the news media industry, which explains why Django naturally excels at content management. Django follows the MTV (Model-Template-View) architectural pattern, which is essentially the same as MVC but with different naming. After 20 years of evolution, Django has become a cornerstone of the Python web ecosystem — large-scale platforms like Instagram, Pinterest, and Disqus have all used or continue to use Django for their core services. This kind of maturity, battle-tested in large-scale production environments, is the core value of "boring, old technology."

After trying Rails, she ultimately chose Django. The core reason: Django is more explicit rather than relying on conventions. For people who might set a project aside for months or even years before coming back to it, code readability and traceability are crucial.
Less "Magic" Than Rails
The author tried learning Rails in 2020 but found that Rails' "convention over configuration" philosophy was an obstacle for her. For example, writing a single line resources :topics in routes.rb doesn't tell you directly where the specific route configurations are — you have to remember or look up the convention rules.
The Fundamental Difference Between Two Philosophies Rails' "Convention over Configuration" philosophy, proposed by DHH, centers on reducing configuration code through a large number of preset conventions, allowing developers to focus on business logic — developers familiar with the conventions can get up to speed on new projects extremely quickly. Django, on the other hand, aligns more closely with the Zen of Python's principle that "Explicit is better than implicit," where every behavior has a clear code counterpart. Each philosophy involves tradeoffs: conventions reduce initial code volume but increase cognitive load, requiring developers to internalize framework rules as muscle memory; explicitness increases code volume but lowers the cost of understanding, allowing even strangers to infer system behavior by reading the code. For projects with long-term maintenance needs, high team turnover, or intermittent development, explicit design tends to be more sustainable.
In Django, a small project typically only requires attention to 5 core files:
urls.py— Route configurationmodels.py— Data modelsviews.py— View logicadmin.py— Admin backendtests.py— Test code
If you want to find where a particular HTML template lives, you can usually trace it through explicit references in these files. This transparency makes projects easy to understand even after being shelved for a long time, and it gives Django a gentler learning curve.
Built-in Admin Backend: Out-of-the-Box Productivity
One of Django's most delightful features is its built-in Admin interface. With just a small amount of code, you can customize a fully functional data management backend:
@admin.register(Zine)
class ZineAdmin(admin.ModelAdmin):
list_display = ["name", "publication_date", "free", "slug", "image_preview"]
search_fields = ["name", "slug"]
readonly_fields = ["image_preview"]
ordering = ["-publication_date"]
This code configures the display fields, search fields, and default sorting for the list view. Under the hood, Django Admin is itself a complete Django application that reads model metadata (Meta class) to automatically generate CRUD interfaces, with support for enterprise-grade features like permission management and history tracking. For scenarios where you need to manually view or edit database data, Django Admin is far more efficient than building a management interface from scratch — it's especially well-suited for personal projects and small teams.
The Appeal of the ORM: From "Who Needs It" to "This Is Actually Great"
The author's previous attitude was "ORM? I'll just write SQL myself." But Django's ORM changed her mind.
How ORM Technology Works ORM (Object-Relational Mapping) is a technique that maps object models in object-oriented programming languages to relational database table structures. Its core value lies in letting developers manipulate databases using an object-oriented approach without writing SQL directly, while also providing database dialect abstraction — the same ORM code can switch between SQLite, PostgreSQL, and MySQL without modifying business logic. Django ORM's double-underscore query syntax (Lookup API) is one of its most distinctive designs: through the chained syntax of
field__related_field__condition, the ORM engine automatically analyzes ForeignKey and ManyToManyField relationships between models and generates the corresponding SQL JOIN statements. This design maintains readability while making the construction of complex queries intuitive, and the generated SQL is well-optimized.
A typical example uses __ (double underscore) to represent JOIN operations:
Zine.objects.exclude(product__order__email_hash=email_hash)
This single line of code involves a query joining 5 tables (zines, zine_products, products, order_products, orders). You only need to declare ManyToManyField relationships in your models, and Django knows how to join these tables.
Compared to writing complex SQL JOIN statements by hand, product__order__email_hash requires less typing and is more readable. For small projects, the performance of ORM-generated queries is absolutely not an issue.
Automatic Migrations: A Powerful Tool for Data Model Changes
Another huge benefit of Django's ORM is automatic migrations. When you add, remove, or modify fields in models.py, Django automatically generates migration scripts (like migrations/0006_delete_imageblob.py). The migration system tracks every model change and forms an ordered version history, similar to Git version control for your database structure. This feature is especially important during the early stages of a project when you're frequently adjusting data models — you don't need to manually write ALTER TABLE statements or worry about missing a change. During team collaboration, each member simply needs to run python manage.py migrate to sync the database to the latest state.
A Practical Choice: SQLite Instead of Postgres
After experiencing the pain of managing Postgres, the author decided to run all her small websites on SQLite.
Reconsidering SQLite for Production SQLite is the most widely deployed database engine in the world, designed for embedded scenarios rather than client-server architectures, with the entire database stored in a single file. For a long time, SQLite was considered unsuitable for production environments, but this perception is being reassessed. The official SQLite documentation states that for applications with fewer than 1 million writes per day, SQLite's performance is more than adequate. In 2022, the emergence of tools like Litestream further addressed SQLite's real-time backup and streaming replication challenges. Django 4.2 also specifically optimized SQLite support by introducing WAL (Write-Ahead Logging) mode configuration — WAL mode allows read and write operations to proceed concurrently, significantly improving throughput in concurrent scenarios and making SQLite's performance in web application contexts far exceed traditional expectations.
The benefits are obvious:
- Backups require just
VACUUM INTOfollowed by copying a single file - No need to manage a database service process
- More than sufficient for small sites with a few hundred writes per day
She referenced community guides for SQLite production environment configuration and cited her own project "Mess with DNS" (which has higher write volumes spread across 3 SQLite databases) as a successful case study. The Django + SQLite combination is a seriously underestimated, highly efficient solution for personal projects and small websites.
The "Batteries-Included" Framework Philosophy
Django's "batteries-included" philosophy is reflected everywhere: CSRF protection, Content-Security-Policy, email sending, and more are all built in.
Built-in Web Security Mechanisms CSRF (Cross-Site Request Forgery) is a common web security attack where an attacker tricks a logged-in user into unknowingly sending malicious requests to a target website — for example, completing a bank transfer without the user's knowledge. Django's CSRF protection works by injecting a random token into forms (via the
{% csrf_token %}template tag) and verifying it on the server side. This mechanism is enabled by default and requires no additional configuration. Content-Security-Policy (CSP) provides another layer of defense by using HTTP response headers to tell browsers which resource origins are trusted, thereby preventing XSS (Cross-Site Scripting) attacks. Django provides these security mechanisms as built-in middleware, and the middleware architecture allows cross-cutting concerns to be inserted into the request-response cycle — embodying the principle of "secure by default."
Related articles
TutorialsChatGPT Plus Subscription Guide: Are GPT-5.5, image-2, and Codex Worth the Upgrade?
A detailed look at ChatGPT Plus features — GPT-5.5, image-2, and Codex — with a Plus vs Pro comparison and a complete step-by-step subscription guide for users outside the US.
TutorialsHarness AI Engineering in Practice: Using Claude Code to Master Enterprise-Level E-Commerce Development
Deep dive into Harness AI Engineering: master enterprise e-commerce development with Claude Code using the Rules, Skills, Wiki, and Changes framework.
TutorialsCursor + Codex Dual-IDE Collaboration: A Practical Methodology for Open-Source Project Customization
A complete methodology for open-source project customization based on real-world experience, detailing the Cursor+Codex dual-IDE workflow, seven-stage process, MVP validation, and AI source code reading techniques.