Why Django?

Introduction
In this article, I’ll explain why we chose to use Django for Webucator’s website and web applications. I’ll start by explaining what Django is and then I’ll discuss our application needs, and how Django can be used to solve these types of needs.
What is Django?
In a nutshell, Django is a web framework used to create database-driven websites and web applications. But this doesn’t tell you much. You could say the same about programming languages like PHP and ColdFusion, content management systems like WordPress and Drupal, and frameworks like ASP.NET and Java Spring.
So, what makes Django different? Three major things:
- The simplicity of the web framework itself.
- The “batteries included” philosophy.
- Python and the thousands of packages created by the Python community.
Together, these three things make it possible to get a new web application up and running quickly (to see for yourself, try our free Writing Your First Django App course) with virtually no limitations on the type or scale of the application. Plenty of huge websites use Django, including Instagram, Pinterest, Mozilla, Disqus, and National Geographic.*
Webucator Web Applications
Like a lot of companies, we have many different web applications, including:
- Our public website.
- An admin backend for keeping courses up to date, scheduling classes, and managing users (including staff, trainers, clients, students, partners, and courseware authors).
- An application for creating and maintaining courseware and self-paced courses. The courseware source files for this application are maintained in GitHub repositories, which the application pulls from to update materials.
- A self-paced course interface built using Vue.js and an API for connecting to the database.
- Portals for clients of private classes, students in public classes, and trainers.
To make this more relevant to more people, I’ll break this down into common needs:
- A database-driven website.
- An admin site for managing website content and user access.
- Private areas of the website that are exclusive to specific types of users.
- A responsive client-side application (likely built with a JavaScript framework such as React, Vue.js, or Angular) that interacts with the database via an API.
- Special needs that go beyond what you would expect any web framework to have built in (e.g., programmatically connecting to GitHub).
Database-driven Website
Chances are the main website you’re building or want to build is database driven, meaning much of the content on the website is managed in a database. If this is not the case, Django is probably not the right solution for you.
Database-driven websites usually have, at a minimum, these requirements:
- A database.
- A user-management system. You need to be able to differentiate between authenticated users and anonymous users, and between users who are allowed to manage data and those who are not. This further implies that you need:
- An authentication system.
- A permissions system.
- A way to create the pages that your website visitors will see.
- A sitemap – for public-facing websites.
Django’s Database Options
The first requirement for a database-driven website is the database itself. Django supports the following databases:
- PostgreSQL (most popular choice for both Python and Django developers)
- MariaDB
- MySQL
- Oracle
- SQLite
- Microsoft SQL Server – through 3rd-party package
- CockroachDB – through 3rd-party package
- Firebird – through 3rd-party package
Unless you have a reason not to, I recommend using PostgreSQL, largely because that’s the database most Django developers choose – a fact which translates into better community support.
Most applications will include a models.py file, which defines the data models used by the applications. These models map to the database through migrations. Each time you add or change a model, you will run the following code:
python manage.py makemigrations
python manage.py migrate
The first line creates the migration files that contain the code to modify the database. The second line runs those migrations files.
Django’s User-Management System
The second requirement for a database-driven website is a user-management system for creating, managing, and authenticating users, and for managing those users’ permissions.
Django comes with a built-in User
model, which includes the following fields:
username
password
email
first_name
last_name
is_active
is_staff
is_superuser
date_joined
After installing Django, one of the first things you will do is create a superuser, which is as simple as:
python manage.py createsuperuser --username=YOUR_USERNAME --email=YOUR_EMAIL
This will add a user with the is_superuser
boolean field set to True
to the users_user
table that gets created using Django’s built-in User
model, which you can (and probably should) extend so that you can customize the model to meet the needs of your application. See Specifying a custom user model in the documentation.
Superusers can view, add, change, and delete all records in the database through the built-in Django admin (discussed below).
In addition to an is_superuser
field, the User
model includes an is_staff
boolean field. Users with is_staff
set to True
can log into Django admin, but, by default, have no permissions to view, add, change, or delete records. When such users log in, they will see something like this:
Permissions can be granted through code and/or through a built-in widget in the Django admin:
Django also comes with a Group
model, which makes it easy to add users to groups and create group-level permissions.
Django’s built-in authentication system provides views for logging in and out and for managing passwords.
Django’s built-in authentication system provides the base features you need, but you’re likely going to want to build upon those features. An excellent 3rd-party package called django-allauth can make this process much easier. In addition to beefing up the built-in authentication, registration, and account management systems, django-allauth supports a bunch of providers for social authentication, including Twitter, Facebook, Amazon, GitHub, LinkedIn, and many more, and templates for the many registration- and authentication-related views and emails.
Django’s Method for Creating Pages
The third requirement for a database-driven website is a way to create pages using data from the database.
Another way to think of this is: How does Django handle an HTTP request? For example, when someone visits www.example.com/some-page/
, how does Django determine what to return?
An application in Django will typically include the following files (and folder):
- urls.py – This file maps URLs to views. Those URLs can be exact or can use regular expressions to catch patterns. When an HTTP request is made, Django attempts to match the URL requested to a view, which must be imported into the file (usually from the views.py file in the same application).
- views.py – This file contains the views, which may do many things (e.g., query the database using the models defined in the models.py file, log information, send emails, etc.) and must return an HTTP response. That response generally contains HTML, which is generally created from a template in the templates folder.
- templates – This folder contains the templates used by the views to create the HTML (usually) that gets returned with the HTTP response. Django includes a built-in, easy-to-use, and extensible template language, which supports variables and template tags and filters for adding programming functionality.
- some-page.html – a template that gets used by a view.
Django’s Built-in Sitemap Generation
The fourth requirement for a database-driven website, at least a public-facing one, is a sitemap.
See https://www.webucator.com/sitemap.xml for an example of a sitemap generated using Django’s built-in sitemap framework, which makes whipping up a single-page sitemap or a sitemap index super easy.
Admin Site
In addition to managing users, you will need to manage the data in the database that drives your website. For Webucator, that includes courses, course tags, class dates, and articles like the one you’re currently reading. True to its “batteries-included” philosophy, Django provides a built-in admin site that makes it easy to manage such data.
To manage a model (i.e., a database table) in the Django admin, all you have to do is:
- Register the model.
- Grant view, add, change, and delete permissions to the appropriate users.
This will create the following pages:
- A page for viewing and searching the model objects (i.e., the table records).
- A page for adding a new object/record.
- A page for changing or deleting an object/record.
Usually, you will also create a Python class that extends admin.ModelAdmin
, so that you can customize the admin pages for a particular model. For example, you can:
- Control the fields that show up in the list view.
- Control the fields that are included in the add and change forms, and the order in which they appear.
- Add fields from related tables to the change form. For example, for a polling application, you might have a
Question
model and a relatedChoice
model, which holds the possible choices for each question. Although they are separate models, it makes sense to manage the choices from within the question form:Django makes this easy to do.
Private Areas of Website
It is common for websites to have private areas for specific types of users. These might include web-based reports for staff and partners or access to special areas for certain types of clients. For example, at Webucator, self-paced students get access to their courses, and their managers get access to reports on their progress through those courses.
Django provides different ways of limiting access to views via mixins, which are used add functionality to a class, and decorators, which are used to add functionality to a method.
Here are a couple of examples straight from the Django documentation:
UserPassesTestMixin
Mixin
from django.contrib.auth.mixins import UserPassesTestMixin
class MyView(UserPassesTestMixin, View):
def test_func(self):
return self.request.user.email.endswith('@example.com')
user_passes_test
Decorator
from django.contrib.auth.decorators import user_passes_test
def email_check(user):
return user.email.endswith('@example.com')
@user_passes_test(email_check)
def my_view(request):
...
Whether you use the mixin or the decorator, you have full control over what happens when a user does not have permission to access the view. For example, you can redirect unauthenticated users to a login page and show a friendly “Permission Denied” message to authenticated users who don’t have access to this view.
Client-side App
When you build a client-side app, you use JavaScript (or a JavaScript framework such as React, Vue.js, or Angular) to respond to user actions. If the app you’re building needs to retrieve data from and/or push data to the database, you need to make sure the server-side technology you choose provides a good solution for integrating with your client-side framework. Generally, this means it must provide a framework for building web APIs. Enter Django REST Framework. Its major benefits include:
- It makes it easy to require authentication and check user permissions.
- It provides simple serialization methods for converting Python objects to JSON and vice versa.
- The coding experience is similar to Django’s, which makes it relatively easy to learn.
Special Needs
Earlier, I mentioned that our courseware application pulls from GitHub repositories to keep courses up to date. To do this, we rely on two third-party libraries: PyGithub and pygit2. Most web applications won’t have this particular need, but they will have their own special needs that go beyond what you would expect any particular web framework to have built in. That’s why it’s beneficial to work with a framework that’s been around a long time (Django 1.0 was released in 2008), that’s built with a powerful and popular programming language (for Django, that’s Python), and has a strong development community that provides thousands of time-tested libraries for adding additional functionality to your web application.
Check out the Python Package Index (PyPi) to search for Python libraries created by the huge Python community. You will find libraries for connecting the AWS services like S3, sanitizing HTML from untrusted sources, testing, working with XML, validating epub files, adding rich text editors to your site, creating and converting caption files for videos, and much more. Chances are, if you need it, some Python/Django developer has needed it before you, and has created a library that you can use.
Conclusion
According to the official Django website, the answers to “why Django?” are:
- Developing in Django is “ridiculously fast.”
- Django is “fully loaded,” meaning it has built-in ways for handling most common web development tasks.
- Django is “reassuringly secure,” with built-in secure user authentication and built-in ways for preventing common attacks.
- Django is “exceedingly scalable,” meaning it can handle loads of traffic.
- Django is “incredibly versatile,” meaning it can be used for all sorts of different types of web applications.
We believe that all of this is true. We have been incredibly happy with Django. If you’re building a new web application, I highly recommend you give it a look-see.
And if you need any training, please give us a shout or check out our Django courses.