Django tutorial: Get started with Django 2.0

Get up and running with routes, views, and templates in Python’s most popular web framework

Django tutorial: Get started with Django 2.0

Django is a one-size-fits-all Python web framework that was inspired by Ruby on Rails and uses many of the same metaphors to make web development fast and easy. Fully loaded and flexible, Django has become one of Python’s most widely used web frameworks.

Django includes virtually everything you need to build a web application of any size, and its popularity makes it easy to find examples and help for various scenarios. Plus Django provides tools to allow your application to evolve and add features gracefully, and to migrate its data schema (if it has one).

Django also has a reputation for being complex, with many components and a good deal of “under the hood” configuration required. In truth, you can get a simple app up and running in relatively short order, then expand its functionality from there as needed.

In this guide we’ll walk through the creation of a rudimentary Django 2.0 app, and touch briefly on the most crucial features it provides for web developers.

Upgrading from Django 1.x

If you have experience with an earlier, 1.x edition of Django, these are the most important breaking changes to be conscious of:

  • Django 2.0 only supports Python 3.4 and up. Python 2.x will not be supported in future versions of Django.
  • Django 2 follows Python 3’s pattern of using native Unicode strings wherever possible. Some Django functions will no longer accept bytestrings as input. 

There are many other backward incompatible changes, but those are two of the most significant, especially when starting new projects.

Installing Django’s core libraries

To install Django 2.0, you will need Python 3.4 or better. Then the easiest way to install Django is via Python’s pip utility:

pip install django

This installs the core Django libraries and the django-admin command line utility used for managing Django projects.

If you want to work with multiple versions of Django side by side, create a virtual environment, install your desired version of Django there, and use that for the Django project in question.

Note that you do not need to use virtual environments to create multiple projects with a single instance of Django. You only need them to use different point revisions of the Django framework with different projects.

Creating a new Django project

Django instances are organized in two tiers: projects and apps.

  • A project is an instance of Django with its own database configuration, settings, and apps. It’s best to think of a project as a place to store all the site-level configurations you’ll use.
  • An app is a subdivision of a project, with its own route and rendering logic. Multiple apps can be placed in a single Django project. 

To create a new Django project from scratch, enter the directory where you want to store the project and type:

django-admin startproject <project_name>

where <project_name> is the name of both the project and the subdirectory where the project will be stored. Be sure to pick a name that isn’t likely to collide with a name used by Python or Django internally. A name like myproj will work just fine.

The resulting directory should contain a file, which is used to control the app’s behavior from the command line, and another subdirectory (also with the project name) that contains the following files:

  • An file, which is used by Python to designate a subdirectory as a code module.
  •, which holds the settings used for the project. Many of the most common settings will be pre-populated for you.
  •, which lists the routes or URLs available to your Django project, or that the project will return responses for.
  •, which is used by WSGI-compatible web servers, such as Apache HTTP or Nginx, to serve your project’s apps.

Before anything else, test the project to make sure it’s functioning. From the command line in the directory containing your project’s file, run:

python runserver

This should start a development web server available at Visit that link and you should see a simple welcome page that tells you that the installation was successful.

Note that the development web server should not be used to serve a Django project to the public. It won’t scale to handle the needed traffic.

Creating a Django app

Next we need to create an app inside this project. Navigate to the same directory as and issue this command:

python startapp myapp

This creates a subdirectory for an app named myapp that contains the following:

  • A migrations directory. Contains code used to migrate the site between versions of its data schema.
  • Contains objects used by Django’s built-in administration tools. If your app has an admin interface or privileged users, you would configure the related objects here.
  • Provides configuration information about the app to the project at large, by way of an AppConfig object.
  • Contains objects that define data structures used by your app to interface with databases.
  • Contains any tests used to ensure that your site’s functions and modules are working as intended.
  • Contains functions that render and return responses.

To start working with the app, we must first register it with the project. To do this, edit myproj/ and add a line to the top of the INSTALLED_APPS list:


If you look in myapp.apps, you’ll see a pre-generated object named MyappConfig, which is what we’re referencing here.

Adding routes and views to your Django app

Django apps follow a basic pattern for processing requests:

  • When an incoming request is received, Django parses the URL for a route to apply it to.
  • Routes are defined in, with each route linked to a view, i.e. a function that returns data to be sent back to the client. Views can be located anywhere in a Django project, but they’re best organized into their own modules.
  • Views can contain the results of a template, i.e. code that formats requested data according to a certain design.

To get an idea of how all these pieces fit together, let’s modify the default route of our sample app to return a custom message.

Routes are defined in in a list named urlpatterns. If you open the sample, you’ll see urlpatterns already predefined:

urlpatterns = [

The path function—a Django built-in—takes a route and a view function as arguments and generates a reference to a URL path. By default, Django creates an admin path that is used for site administration, but we need to create our own routes.

Add another entry, so that the whole file looks like:

from django.contrib import admin
from django.urls import include, path

urlpatterns = [
    path(‘myapp/’, include(‘myapp.urls’))

The include function tells Django to look for more route pattern information in the file myapp.urls. All of the routes found in that file will be attached to the top-level route myapp (e.g.,

Next, create a new in myapp and add the following:

from django.urls import path
from . import views

urlpatterns = [
    path(‘’, views.index)

Django prepends a slash to the beginning of each URL, so to specify the root of the site (/), we just supply a blank string as the URL.

Now edit the file myapp/ so it looks like this:

from django.http import HttpResponse

def index(request):
    return HttpResponse(“Hello, world!”)

django.http.HttpResponse is a Django built-in that generates an HTTP response from a supplied string. Note that request, which contains the information for an incoming HTTP request, must be passed as the first parameter to a view function.

Stop and restart the development server, and navigate to You should see Hello, world! appear in the browser.

Adding routes with variables in Django

Django can accept routes that incorporate variables as part of their syntax. Let’s say you wanted to accept URLs that had the format year/<int:year>. You could accomplish that by adding the following entry to urlpatterns:

path(‘year/’, views.year)

The view function views.year would then be invoked through routes like year/1996, year/2010, and so on, with the variable year passed as a parameter to views.year.

To try this out for yourself, add the above urlpatterns entry to myapp/, then add this function to myapp/

def year(request, year):
    return HttpResponse(‘Year: {}’.format(year))

If you navigate to /myapp/year/2010 on your site, you should see Year: 2010 displayed in response. Note that routes like /myapp/year/rutabaga will yield an error, because the int: constraint on the variable year allows only an integer in that position. Many other formatting options are available for routes.

Earlier versions of Django had a more complex and difficult-to-parse syntax for routes. If you still need to add routes using the old syntax—for instance, for backward compatibility with an old Django project—you can do so by using the django.urls.re_path function.

Django templates

Django’s built-in template language can be used to generate web pages from data.

Templates used by Django apps are stored in a directory that is central to the project: <app_name>/templates/<app_name>/. For our myapp project, the directory would be myapp/templates/myapp/. This directory structure may seem a little awkward, but Django can look for templates in multiple places, so this avoids name collisions between templates with the same names across multiple apps.

In your myapp/templates/myapp/ directory, create a file named year.html with the following content:

Year: {{year}}

Any value within double curly braces in a template is treated as a variable. Everything else is treated literally.

Modify myapp/ to look like this:

from django.shortcuts import render
from django.http import HttpResponse

def index(request):
    return HttpResponse(“Hello, world!”)

def year(request, year):
    data = {’year’:year}
    return render(request, ‘myapp/year.html’, data)

The render function, a Django “shortcut” (a combination of multiple built-ins for convenience), takes the existing request object, looks for the template myapp/year.html in the list of available template locations, and passes the dictionary data to it as context for the template.

The amount of processing you can perform on data within Django templates is intentionally quite limited. Django’s philosophy is to enforce separation of presentation and business logic whenever possible. Thus you can loop through an iterable object, and you can perform if/then/else tests, but modifying the data within a template is frowned upon.

For instance, a simple “if” test can be encoded this way:

{% if year > 2000 %}
21st century year: {{year}}
{% else %}
Pre-21st century year: {{year}}
{% endif %}

The {% and %} markers delimit blocks of code that can be executed in Django’s template language.

If you want to use a more sophisticated template processing language, you can swap in others, such as Jinja2 or Mako. Django includes back-end integration for Jinja2, but any template language that returns a string can be used—for instance, by returning that string in a HttpResponse object as in the case of our ”Hello, world!” route.

Next steps with Django

What we’ve seen here covers only the most basic elements of a Django application. Django includes a great many other components that can be employed in a web project. All of these are worth discussing in detail separately, but I will leave you with a brief overview:

  • Databases and data models. Django’s built-in ORM can be used to define data structures and relationships between them for your app, as well as migration paths between versions of those structures.

  • Forms. Django provides a consistent way for views to supply input forms to a user, retrieve data, normalize the results, and provide consistent error reporting.

  • Security and utilities. Django includes many built-in functions for caching, logging, session handling, handling static files, and normalizing URLs. It also bundles tools for common security needs like using cryptographic certificates, or guarding against cross-site forgery protection or clickjacking.

Copyright © 2018 IDG Communications, Inc.