Why Django is probably the best web framework
Tags: programming, webdev, beginners, productivity
Published: 2023-12-03 10:44:38

Most modern stacks are just fine for most projects, however, I have a special bias toward Django. It's stood the test of time and is rock solid with a ton of features baked in.

Ironically I do not use Django often but do have a lot of experience in it. My day job involves Golang and PHP-based frameworks like Laravel, which are fine and work well, however, every so often I get to go back to Django and it's always a great experience.

## Why Django?
 
Since Django is built on Python, it inherits all the great things about Python. Python is one of the most loved languages around because it's easy to understand and has a great open-source community.

Furthermore, Django is mature and battle-tested - it's been around since 2003 or thereabout and has been used in projects of varying scales including high-traffic platforms like Instagram.

## HMVT

Django uses something called "MVT", or "Model View Template". Essentially this is MVC because the "V" in MVT refers to views.py which is a controller - thus the "C" in "MVC". "T" in MVT refers to templates, which is essentially the "V" in MVC (Wow that's confusing right?).

Anyway, besides the weird acronym - this is a very clean and easy-to-use pattern, it ensures your code is separated into 3 layers that make sense for most web projects.

Django, however, takes it one step further with "apps". What I like to refer to as "Hierarchal Model View Template". HMVT separates your code into modules that are usually self-contained and portable.

This not only allows you to group related functionality into modules ("apps") but also allows sharing these modules between projects, thus DRY.

An example would be an "account" app, in the account app - you can put all logic relating to the user account such as:

1. Authentication.
2. User's profile CRUD.
3. 2 factor autentication.

and so forth...

Next, you can create a blog app with this functionality:

1. CRUD for posts.
2. CRUD for taxonomy.
3. CRUD for tags.
4. Comments.

Besides the portability benefit, it also makes navigating through your codebase a lot simpler.

## Batteries included

Django has a ton of functionality such as database management, CLI commands, emails, templating, a full-featured admin, and so on, already baked into the framework.

Furthermore, these are all maintained by Django and have excellent documentation. You do not need to worry about individual versioning as you would do in something like Next.js - where different projects could use a whole host of different packages.

Then, there is Python, which has a package for everything.

## Django Admin

If you have ever needed to build internal tooling at your company or just need a simple CRUD for your frontend - you would understand the pain of CRUD, authentication, and all the plumbing stuff. 

Django Admin is incredibly powerful and simple to implement, you extend a base class and can have a working crud in minutes.

Example:
```python

from blog.models import Post
admin.site.register(Post) 

# Run this in your terminal to create an admin user
python3 manage.py createsuperuser

# Run this to start Django's test server
python3 manage.py runserver
```

Next, simply visit the following URL to access your admin dashboard:

```
http://127.0.0.1:8000/admin
```

Customizing the admin dashboard is a bit of a learning curve when you want to do something more advanced, but for the amount of functionality you get out of the box - this is well worth your time learning. You will end up saving hours if not days of work in the long run.

## Types

I see this complaint a lot on the internet, that Python is not a typed language and types just make your code more robust and safer.

Yes, strongly typed languages such as C#, Golang, and so forth do give you that added benefit of having a compiler check your code and catch silly errors. This is nice and goes a long way in helping you write better code.

Types though aren't everything. Both Python and Django do provide some great functionality to help mitigate some of the risks with a dynamic language:

1. In models and forms, each field is essentially typed and the model/form itself is a type. Besides making code completion work a lot better, this also forces you to write code mindful of types.
2. Python does support type hinting:
```python
def addNumbers(num1: int, num2:int) -> int:
    return num1+num2
```
3. Unit testing - Django has excellent tooling to help with unit tests. Types alone don't catch everything - a unit test on the other hand provides a much more robust way of testing code to ensure code quality.

## Django templates

Django templates are easy to understand and work with, they use essentially a simplified version of Python. You don't have to worry about state, props, and all the complexities you would find in a UI framework like React.

With templates alone, you can get quite far, and then just use a sprinkle of standard JavaScript where you need a bit of interactivity.

Furthermore, you can extend Django templates with libraries like Django Unicorn, HTMX, or alpine.js.

Some examples:
```python

# Simple IF statement
{% if form.errors %}
  <p>Oops, please fill in all required fields.</p>
{% endif %}

# Simple for loop
<ul> 
{% for user in users %} 
    <li>{{ user.name }}</li> 
{% endfor %} 
</ul> 
```

## Django is dependable

Early on in my career - I wrote Django often, almost daily till about 2015/2016, and then haven't touched it much since. In 2022, I started to refresh my memory again - to my surprise - not much has changed.

Django in 2015 was around version 1.9 and today it's at version 4. Furthermore, I was still on Python 2.7 but now I am running Python 3.10.

Many of the packages shipped with Django or part of the Django core have had several under-the-hood updates in the last 8-10 years as well.

Yet despite all these changes, the knowledge I gained in 2015 and earlier, about models, views, templates, and everything else Django-related - still looks and works 90% the same.

There are a few minor tweaks here and there and some new stuff but overall, I haven't encountered any major breakages while upgrading to Django 4+. For a Python project, this is incredible (Python has a reputation for breaking backwards compatibility).

Compare this to a 2018 React project, in 2023 - so much has changed, when I tried to upgrade - several things broke. It was painful and even worse - there were JavaScript package issues besides React itself, not to mention a whole new coding style with hooks.

I love evolution in tech and new tools as much as anyone else, however, Django tends to carefully take its time when making changes to the core library.

This keeps the framework stable and allows developers time to gradually update their skill set. In terms of business - as a member of senior staff in most teams I work with, it's much easier to sell Django, compared to other flavor-of-the-month projects.

Businesses don't care about the latest and greatest, they want to invest in stacks that will be easy to maintain and have a solid proven track record. They don't want to keep upgrading the framework every year.

This is why Django is always a sold choice.

## Documentation

The Django documentation is well-written and covers the entire framework with great detail. Just reading the docs alone is sufficient to become productive in Django without any additional tutorials.

Furthermore, it's all in one place - since Django is batteries included, for 80% of the time you will be using standard libraries. When you get stuck, it's quite easy to find documentation in the Django docs.

If all else fails, Django has a large community on stack overflow and other popular platforms.


## How to get started with Django?

As mentioned above - Django is MVT-based. The core concepts to learn:

1) Each MVT app in Django has a similar structure:
- blog/urls.py - routes
- blog/views.py - controller
- blog/models.py - all db table models
- blog/admin.py - admin dashboard logic
- templates/ - normally at the project root, but it's possible to also add templates to each app.

2) Routes (urls.py):
```python
from django.urls import include, path
from blog import views

urlpatterns = [
    path("blog/", views.list, name="blog-index"),
    path("posts/new", views.create_post, name="blog-create-post"),
    path("posts/edit/<int:pk>/", views.edit_post, name="blog-edit-post")
]
```
3) Models (models.py)
```python
from django.db import models

class Post(models.Model):
    title = models.CharField(max_length=255)
    body = models.TextField()
```

4) Views (views.py)
```python
from django.shortcuts import render
from blog.models import Post

def list(request):
    posts = Post.objects.all()
    context = {
        "posts": posts,
    }
    return render(request, "blog/index.html", context)
```

5) Templates (templates/blog/)
```python
{% for post in posts %}
   <h3><a href="{% url 'blog-posts-view' post.pk %}"> 
    {{post.title }}</a></h3>
 
   <p>{{ post.body}}</p>
{% endfor %}
```
6) Model queries
```python
# Saving a model
p = Post(title="Django Rocks", body="Django is an amazing framework.")
p.save()

# Get by ID
post = Post.objects.get(pk=1)

# Get by title
post = Post.objects.get(title="Django Rocks")

# Update a post
post.body = "Some new description"
post.save()

# Find posts that start with
posts = Post.objects.filter(title__startswith="Django")
```
Learn more about queries here: [https://docs.djangoproject.com/en/4.2/topics/db/queries/](https://docs.djangoproject.com/en/4.2/topics/db/queries/)

## Conclusion

Django is an amazing framework, it has everything you need to build any kind of web application. 

Pair Django with HTMX or Django Unicorn, and you have a full-stack beast that can give your users a great user experience whilst still being able to handle complex engineering tasks on the server side.

While Django scales up pretty easily to support large enterprises, it is perfect for small teams, freelancers, and even solo developers.

The development speed, simplicity, and awesomeness of Python will make you super productive and ship to market much faster.