Getting Started with Django

Django is a rapid development framework for web applications, written in Python.

A development framework is an application skeleton, with a set of tools for building software quickly, and an opinion about how software should be built.

Frameworks reduce "boilerplate" code by providing the most common features — database connectivity, user logins, session management, request routing. These are needed in almost every application, regardless of the app's specific purpose, and they don't need to be redesigned for each new project.

A development framework also provides an architecture for the system. Rather then spending time and energy deciding how to organize code (or having never ending problems from failing to do so), a framework has a right way to organize features, so you can just start creating them.

We'll see what that structure looks like as we walk through setting up a first app.

Getting Started

The only thing you really need is access to the internet, a very basic knowledge of the command line, and a code editor.

Most Linux users likely know how to access their Terminal, but here is a quick guide to Linux terminal in case you don't. If you are on a Mac OS X, you have a Linux/Unix-like command line accessible in the Terminal app.

The Windows command line is a bit different from the one on Mac OS X and Linux (called bash ). You can use the Windows Powershell, but you'll have to "translate" quite a bit — not just here but in most other tutorials and reference guides. The easiest approach is probably to simply install a bash terminal.

You have a few options:

Installing Everything

There are a number of steps to getting Django running: Python, Upgrade the Python package manager, set up your virtual environment, and install Django.
Python
If you don't have Python on your computer, you need it. See the Python Downloads page for links to Python for all the major operating systems. You'll want Python 3, not Python 2. You can use Python 2 with Django, but Python 3 is the present and future of the language. If you are just getting into Python and Django, use Python 3. You might have Python 2 on your computer already. As of this writing Mac OS X ships with Python 2, and a few Linux distributions do as well. Install Python 3 and use it. (Having two versions of Python on your computer won't be a problem, as you'll see in the next steps.) If you aren't sure which version of Python you have, type python into the command line. It will tell you. For example, the following is what you'd see if you were running Python version 3.5.1:
> python
Python 3.5.1 (v3.5.1:37a07cee5969, Dec 5 2015, 21:12:44)
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
If running python reveals v2, try python3. If you have Python 3 installed, that should tell you.
Upgrade Python Package Manager
Python ships with pip, the Python package manager. However, you'll need to upgrade it (the Python install bundles don't get upgraded every time pip updates). Fortunately, pip upgrades itself with a quick terminal command:
> pip install --upgrade pip
Python Virtual Environments
Any Python project, including a Django project, is normally going to involve a number of separate third-party packages. If you use Python a lot, you'll eventually have version conflicts — this project needs v4.3 of something while that project needs v5.1. The solution is Python virtual environments. There are several Virtual Environment tools for Python. We use virtualenv. First, install it with pip:
> pip install virtualenv
Next, set up a Virtual Environment for your Django project. Create a new directory that will house your Django project(s). This directory will contain your project directory, and other things, so to keep yourself from getting confused it might be best to give it a name other than your project name. We'll call this one django-projects. Create the container directory, then run virtualenv from inside the directory. When running virtualenv, we'll specify python3 and give the environment a name (djenv), then activate the virtual environment.
> mkdir django-projects
> cd django-projects
~/django-projects > virtualenv -p python3 djenv
~/django-projects > source djenv/bin/activate
(djenv) ~/django-projects >
You are now in a virtual environment named djenv. Any pip packages you install or upgrade will only be available when this Virtual Environment is activated. To deactivate the Virtual Environment, just type deactivate. A quick note on naming things — most documentation for virtualenv, Django, and Python in general uses venv as the name of their example Virtual Environment. Doing that yourself can get confusing, because you might create several different ones on your computer, and it is helpful to remember which is which. Also, venv is the name of another Python Virtual Environment tool. A useful approach is to name the environment something to do with the project (like djenv for django environment ), but you can name it anything you like.
Install Django
This is pretty easy:
(djenv) ~/django-projects > pip install django
You may wish to deactivate your virtual environment and install Django system-wide. It's up to you. Either way, pip will start installing Django and all of its dependencies. This could take some time.

Starting a project

A "project" is (generally) understood to be a single, complete website (or potentially a family of sites). A site might have several different functionalities — a blog, a forum, a store, a help chat. Each one of these is called an "application" (or just "app"). So a project is a collection of apps. This matters for how you structure things, but it also matters for how you name things. Imagine you want to build a new web app that lets people share photos. In your mind, the whole site is "the app." But if you initialize your Django project with the name photo-share-app (or whatever), you're going to get confused with your duplicated directory names.

The structure of a Django project

A Django project's directory structure looks like this:

- /project-name/
   - project-name/
   - app-name/
   - app-name/
   - app-name/
When you first initialize your project, you'll get the top-level project directory, and the second one inside it. The top level acts as a container for the rest of it. The second-level has configuration files for the project as a whole. The new application that you are building will be in one (or more) additional app directories. This creates some annoyances. Assuming you are building some amazing new web app with an awesome name (let's call it wiht ), if you don't think about it, you'll end up like this:

- /wiht/
   - wiht/
   - ?... what should I call the thing I'm building...?/
Here's a suggestion:

- /wiht_site/
   - wiht_site/
   - wiht_app/
This makes everything clear and easy to remember. Also, it makes it easy to simply bolt-on any generic website feature you want to use. Or you can build additional custom apps for yourself, if they make sense as standalone modules:

- /wiht_site/
   - wiht_site/
   - wiht_app/
   - third-party-blog-app/
   - third-party-forum-app/
   - wiht-crm-app/
The Django Docs use mysite, and that's fine for examples. You'll want a unique name for each project. (Of course, you don't have to build a new app to use Django. You could just set up a project and use a collection of existing apps. You can get a complex, multi-function website up and running pretty quickly this way, and have flexibility later to add customer-built apps.)

(Finally) Initialize Your Project

Inside whatever "container" directory (we used /django-projects above), and with your Virtual Environment activated, initialize your new project with the django-admin command.
(djenv) ~/django-projects > django-admin startproject wiht_site
Now you have:

- /wiht_site/
   - manage.py
   - wiht_site/
     - __init__.py
     - settings.py
     - urls.py
     - wsgi.py
Now run the test server to make sure everything happened correctly.
(djenv) ~/django-projects > cd wiht_site
(djenv) ~/django-projects/wiht_site > python manage.py runserver
You'll get some output like:
Performing system checks...

System check identified no issues (0 silenced).

You have unapplied migrations; your app may not work properly until they are applied.
Run 'python manage.py migrate' to apply them.

April 22, 2016 - 17:45:53
Django version 1.9, using settings 'wiht_site.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
Open up http://127.0.0.1:8000 in a browser, and you should see something working: a "Welcome to Django" message.

Initializing your First App

From here, assume we're always in the top-level wiht_site directory (a subdirectory) with the djenv environment activated. When you see this in the examples:
>
Assume you are here:
(djenv) ~/django-projects/wiht-app >
Create a new app with manage.py.
> python manage.py startapp wiht_app
This will create a new directory, /wiht_app/, with the following contents:

 - __init__.py
 - admin.py
 - apps.py
 - migrations/
   - __init__.py
 - models.py
 - tests.py
 - views.py
Now you need to "install" the app. Open /wiht_site/wiht_site/settings.py, and find INSTALLED_APPS. This needs to be edited to include your new app.

INSTALLED_APPS = [
  'wiht_app',
  'django.contrib.admin',
  'django.contrib.auth',
  'django.contrib.contenttypes'
  'django.contrib.sessions',
  'django.contrib.messages',
  'django.contrib.staticfiles',
]

Developing Something

Django apps have something close to a Model-View-Controller architecture, which Django documentation sometimes calls Model-View-Template. This leads to an easy-to-adopt, iterative development pattern:
  • work on the Model, defining what types of data are going to be tracked and how they relate to each other;
  • work on the View, defining how data should be accessed and what to do when data is manipulated;
  • work on the Template, defining how data looks when displayed to the user or consumed by another application.
Models and Migrations
Building new features usually begins with creating models. Models are classes (in the OOP sense) which define the various objects in your system and how they relate to each other. So, in a blog application, you might have models for Post, Page, Category, Comment, and so forth — and maybe a comment is a subclass (a type of) post, and maybe posts and pages are subclasses of ContentItem. Models are written in the models.py file of each app. Here is the beginning of a very simple model for blog posts.

  from django.db import models
  from django.contrib.auth.models import User

  # Create your models here.
  class Post(models.Model):

      title = models.CharField(
          max_length=100,
      )

      slug = models.SlugField(
          unique=True,
      )

      excerpt = models.TextField(
          max_length=255,
      )

      content = models.TextField(
          blank=True,
      )

      author = models.ForeignKey(
          User,
      )

      created = models.DateTimeField(
          auto_now_add=True,
      )

      def __str__(self):
          return self.title

Django has its own Object Relational Mapper (ORM), which provides a layer of abstraction to the database. This allows you to define your data model without reference to a specific database management system, and without having to write SQL. As you add models, you create and then run migrations. A migration is an automatically-generated set to SQL commands that alters the database design to match the models — Django's ORM translates your models into SQL migrations. Before you do that, you'll want to set up your database and connect it. You have a lot of options here, but most Django users prefer PostgreSQL, and there are special PostgreSQL tools for Django that aren't available for other databases. Once you have your database running, you can migrate.
> python manage.py makemigrations
> python manage.py migrate
Admin
Django provides an automatic Admin view on your data, so that you can do basic CRUD operations with your models almost immediately. And if your editing UI needs aren't terribly complex, you can just use the Admin site without building your own editing Views. All you have to do is register the model with the Admin module. This is done in admin.py, inside your application directory.
from django.contrib import admin
from .models import Post

admin.site.register(Post)
Now to log in and access Admin, create a superuser from the command line.
> python manage.py createsuperuser
Follow the in-terminal prompts for username, email, and password. Then start the server:
> python manage.py runserver
And you should be able to log in at http://127.0.0.1:8000/admin/. If everything is configured right, you should be able to view, add, edit, and delete simple blog posts. Now would be a good time to create a handful of sample posts. It'll make the next step more meaningful.
The View
In Django, the "View" isn't the front-end display code (which is called the "Template"). What Django calls the View is more like a "Controller" in other frameworks. It is a function which receives an HTTP Request as an argument, and returns a Response. Typically, the response is the content of a web page which is then accessible from a Template; a response can also be a redirect, an error message, a file, or something else. The most common situation is that you want to send a Request for a particular piece of content (for example, one specific post), and then get back all the data associated with that piece of content (the title, the excerpt, the content, the author). Another common situation is that you want to display a list of content items, like on the front page of a blog or newsfeed. Django provides built-in Generic Views to accomplish these quickly. The two we'll use are ListView and DetailView. If you wanted to extend them, or create your own views, you would do that in views.py, but we'll use them as-is for now. Now we just need to map those views to URLs. In /wiht_site/urls.py, you'll need to include your app-specific URL mapping.

  from django.conf.urls import url, include
  from django.contrib import admin

  urlpatterns = [
      url(r'^admin/', admin.site.urls),
      url(r'^', include('wiht_app.urls') ),
  ]
Then edit your app's urls.py.

  from django.conf.urls import url, include
  from . import views
  from django.views.generic import ListView, DetailView
  from .models import Post

  urlpatterns = [
    url(
      r'^blog/$',
      ListView.as_view(
        queryset=Post.objects.all().order_by("created")[:50],
        template_name="wiht_app/index.html"
      ),
    name='post-list'
    ),
    url(
      r'blog/(?P<slug>[a-zA-Z0-9]+(?:\-[a-zA-Z0-9]+)*)/$',
      DetailView.as_view(
        model=Post,
        template_name="wiht_app/post.html"),
        name="post"
    )
  ]
The url() function which defines each pattern has a series of comma separated arguments: The above patterns match the /blog/ and /blog/post-slug/ URL patterns to the ListView and DetailView, and then specifies their Templates ( index.html and post.html ).
Template
All that's left is to create a template to display this content. Django uses Jinja templating. Create three new files: /wiht_site/wiht_app/templates/wiht_app/main.html
<!DOCTYPE html>
<html>
<head>
</head>
<body>
 {% block content %}
 {% endblock %}
</body>
</html>
/wiht_site/wiht_app/templates/wiht_app/index.html
{% extends "wiht_app/main.html" %}

{% block content %}

<h1>Posts</h1>

 {% for entry in object_list %}
 <h2><a href="/blog/{{ entry.slug }}/" title="{{ entry.title }}">{{ entry.title }}</a></h2>

 {{ entry.excerpt }}

 {% endfor %}

{% endblock %}
/wiht_site/wiht_app/templates/wiht_app/post.html
{% extends "wiht_app/main.html" %}

{% block content %}

<h1> {{ post.title }}</h1>
<div> {{ post.author }} <br>
Posted on: {{ post.created }} </div>
<div>{{ post.content}}</div>

{% endblock %}
Congratulations, you should now have a working blog application.

Further Reading and Resources

We have more guides, tutorials, and infographics related to coding and development: