Django for Designers

Introduction
In this tutorial, we will explain topics and provide commands for you to run on your own computer. You will leave with a working social bookmarking web app!

This is a tutorial on web programming, so we will go beyond just Django and discuss third-party Django apps and other real-world web development tools. We'll also be emphasizing areas of Django that particularly affect designers, such as static files, template inheritance, and AJAX.

Things you should know already

 * HTML familiarity
 * Basic Python proficiency
 * Basic or better Javascript proficiency
 * Pre-requisites that we will help with

We expect you to have git, Python, and a few other elements ready on your laptop before the tutorial. We will publish a laptop setup guide that steps you through:


 * Installing Python, git, pip, virtualenv, and a reasonable text editor
 * Setting up your env with Django, South, and django-debug-toolbar
 * Basic command line knowledge (cd, ls, etc)
 * Basic git knowledge
 * Setting up your git repo for the tutorial

Things you do not need to know already:

 * Django :)
 * What an ORM is
 * Anything database related

Laptop setup
See our /Laptop setup guide.

Part 1: Starting our project
This tutorial goes through the process of building a simple social bookmarking application, where users can save various URLs and tag those bookmarks to make them easier to find later. Our bookmarks application will be built on top of Django, a full-featured web framework written in Python.

Activate your env
The first step is to open your terminal window, navigate to the folder where you plan to store your app code (where you set up your virtualenv for this tutorial earlier) and activate your env:

You'll know it worked because afterwards, you'll see  at the front of all your terminal lines in that terminal window!

Set up your git repo
If you're following this tutorial at PyCon, in your terminal, run:

This will download a few files that we'll be using in this tutorial.

Additionally, this sets us up to use a program called git to save our progress and sync up later, in case any of you get stuck. If you're not familiar with git, git is a version control system that tracks changes you make to files within a git repository (the folder you just cloned). You make commits in git, which are like save points in video games -- the commit messages tell you what changes are included in this commit. If later on you make some changes and delete something or mess something up, you can always go back to a previous commit and try again.

Git also has "branches"--parallel timelines where you can go off from the main branch (called "master") and try something out. It's often a good idea to start a new branch when you're writing a new feature. You can make as many commits as you want inside the branch, and it won't affect the main master timeline. You can make as many branches as you want, and branches of branches. You can even share branches with others (though we won't be doing that today). Git's branching system (and its non-centralized architecture generally) make it easy to try out new ideas in code without having to ask permission of everyone else who might be working on the same code as you. Then, when your new feature is done, you can then merge (or rebase--the exact process would take a much longer explanation) the changes back into the master timeline.

We'll be using the master branch (the default name for the main branch of code, which you're in right now) for syncing up throughout the class in case you get lost. You'll need to make your own branches for playing with the code on your computer, so that it doesn't interfere w. re-syncing later.

To make your first branch, first enter the pycon-django-tutorial directory:

Then enter:

Congratulations! You're now in a branch named my-branch-1!

You can see what branch you are in (and what branches are in your repository) at any time by typing:

Start your project
Let's create your first Django project, which we'll call "myproject".

You'll see we made a folder called "myproject", with some files in it. Let's check them out!

These files are:


 * manage.py: A command-line utility that lets you interact with this Django project in various ways.
 * myproject/: Django auto-creates an folder within your project with the same name as your project that has a number of useful files in it. (This is a recent change; before Django 1.4, Django just put everything in the project folder instead of siloing it.)
 * myproject/__init__.py: An empty file that tells Python that this directory should be considered a Python module. Because of the __init__.py file, you can use import to import myproject.
 * myproject/settings.py: Settings/configuration for this Django project.
 * myproject/urls.py: The URL declarations for this Django project; a “table of contents” of your Django-powered site.

Django comes with some local server software included. The Django development server is not hardy enough for actual production use (please, please don't use it for sites other people are supposed to see!) but it makes it easy to see the changes you make to your web app as you build it. Let's make sure our project works by verifying that the dev server will start:

You should see some output in your terminal that looks like:

Visit http://localhost:8000 in your web browser, and you’ll see a “Welcome to Django” page, in pleasant, light-blue pastel. It worked! :)

Observe the logging that happens in the terminal where your server is running:

which has the format:

Navigate to http://127.0.0.1:8000/some/url/. What changes in the terminal log?

Exit the server by returning to the terminal window where the development server is running and pressing CONTROL-C on your keyboard.

Version control
Before we do anything else, let’s commit our work in git.

As you recall, git lets you create checkpoints over the course of the time a program is being developed. Commits are those checkpoints. Programmers often have to go back into the history of a program to change things--whether it's to diagnose a bug or redesign how a feature works. Programmers also have to have an easy way of being able to edit the same application at the same time, and to share their edits with each other. Thus, besides saving their work the normal way, programmers commit their code using version control software.

Each commit contains the diff--the "difference", all of the changes you made to your code base -- between that commit and the commit before it. Different branches in git share the commits made prior to the branching-off point, then each have their own commit history.

To make a commit, first type  into your terminal. This will let you know what changes git has noticed in your code and which of those changes, if any, are staged and ready to be committed.

"Untracked files" means that git has noticed some new files inside its repository folder, but you haven't told git explicitly that you want it to "listen" for, and track, changes in those files.


 * Add the folder: . What does git status say now?


 * git commit to commit those files. Adding the -m flag lets you say what the 'message' for the commit is in the same line:


 * Look at your changes with  to see your history. Is your commit message there?

Huzzah! We committed our changes so far. Now let's make some more changes!

Set up your settings and database
Now that we have a the scaffolding for our project in place, we can get to work! First, it needs to be configured.

Open /myproject/settings.py in your editor. settings.py is a Python script that only contains variable definitions. Django looks at the values of these variables when it runs your project.

In settings.py, let's find DATABASES. The DATABASES variable is a dictionary (note the ‘{}’ characters) with one key: default.

Notice that the value of default is itself another dictionary with information about the site’s default database.

Set your app to use a sqlite database, in the ENGINE attribute. Sqlite is great for development because is stores its data in one normal file on your system and therefore is really simple to move around with your app. It's not sturdy enough to use for a website in production, though.

Set your app to use a file called 'database.db' to store information for this project.

Does database.db exist right now? (No, but that's okay. It'll get created automatically when it's needed.)

Run git status, then git add and commit your change:

Even though git knows to "listen" to settings.py now, it still won't add it to the 'staging area' for your commit unless you tell it to explicitly with git add.

Notice the INSTALLED_APPS setting towards the bottom of the settings.py. That variable (a python tuple... note the ‘’ symbols) holds the names of all Django applications that are activated in this Django instance. Apps can be used in multiple projects, and you can package and distribute them for use by others in their projects. Some apps (as you can see) are installed by default!

Add South to our list of installed apps. (We'll need it later.)

TODO: Install django-debug-toolbar

Each of our applications makes use of at least one database table, so we need to create the tables in the database before we can use them. To do that, run the following command in your terminal window:

The syncdb command looks at the INSTALLED_APPS setting and creates any necessary database tables according to the database settings in your settings.py file. You’ll see a message for each database table it creates.

When prompted, you’ll get a prompt asking you if you’d like to create a superuser account for the authentication system. Say yes! Use 'super' as your password for now.

Does database.db exist right now? (Yes! Calling syncdb made Django realize it needed a sqlite database file, so it made one for us.)

Save and commit your work!

Projects vs. apps distinction
We’ve talked a little about Django apps and projects. You might be wondering what that nonsense is all about. Here are the things to know: An app is component of a website that does something. South is a Django app. So is our bookmarks app (or it will be, anyway). An app is:
 * single purpose - login, passwords, polls, forum, etc.
 * orthogonal to / independent of other apps - Bookmarks shouldn’t have to know the inside details of authentication, for example.

A project corresponds roughly to a ‘website’: it has a settings.py file, and it may have corresponding databases or other data stores that the apps interact with. As you can remember, Django automatically made a folder for us called myproject, which you can think of as the app that coordinates all the other apps and other parts of the project.

Most projects--those for more complex websites--should use multiple apps, one for each core piece of functionality. Ideally, you should reuse existing free, open source Django apps that other people have written for things like user accounts, image galleries, and other common use cases. [Django Packages http://www.djangopackages.com] is a good resource for finding such apps.

You can find prewritten Django apps for things like bookmarks and tagging, but we'll be writing them ourselves for the sake of learning. :)

Start your first app
In your terminal, write:

If you run

you'll see that now there is a folder called bookmarks/ in your project!

Inside that folder, you'll see:

Let's commit our new app.

Note for tutorial attendees
At the end of each section of the tutorial, I'm going to push our progress so far to the tutorial git repository. If you're doing this tutorial in class, please switch back to the master branch, then pull my changes.

This will make it so that everyone starts out each section with the same working code, so even if you get stuck or confused in one session, you can still keep up.

Remember that *you* shouldn't be putting your modifications inside the master branch, though! Instead, make a new branch for section 2 based off the master code you just downloaded, and let's get going!

M-V-C separation concept
TODO: draw a picture

Model: how the data is organized. Controller: how the logic of the app works. View: How the app looks to the user.

Writing our URLs
The first step to writing your application is to design your URL structure. You do this by creating a Python module called a URLconf. URLconfs are how Django associates a given URL with given Python code.

When a user requests a Django-powered page, the system looks at the ROOT_URLCONF setting, which contains a string in Python dotted syntax. Django loads that module and looks for a module-level variable called urlpatterns, which is a sequence of Python tuples in the following format: (regular expression, Python callback function [, optional dictionary])

Django starts at the first regular expression and makes its way down the list, comparing the requested URL against each regular expression until it finds one that matches.

You might ask, “What’s a regular expression?” Regular expressions, or "regexes", are patterns for matching text. In this case, we’re matching the URLs people go to, and using regular expressions to match whole ‘groups’ of them at once. (If you’d like to learn more about regular expressions, read the [Dive into Python guide to regular expressions http://diveintopython.org/regular_expressions/index.html] sometime. Or you can look at this [xkcd http://xkcd.com/208/]. [Regexpal http://regexpal.com/] is also a super helpful tool for writing a regex.)

In addition to matching text, regular expressions can capture text. Capturing means to remember that part of the string, for later use. Regexes use parentheses to wrap the parts they’re capturing.

For Django, when a regular expression matches the URL that a web surfer requests, Django extracts the captured values (if any) and passes them to a function of your choosing. This is the role of the callback function above. When a regular expression matches the url, Django calls the associated callback function with any captured parts as parameters. These callback functions typically live in one of your apps' views.py, so this will be much clearer after the next section.

When we ran

to create our project way back when, Django created a default URLconf file called `urls.py` inside myproject/.

To write our app's URLs, edit the file myproject/urls.py so it looks like this:

Suppose a visitor to your site goes to http://localhost:8000/tags/awesome/.
 * which regex pattern is tripped?
 * what function is then called?
 * what arguments is that function called with?

Save urls.py. Start the dev server  and try that url out! What happens?

Save and commit your work.

The idea that a URL doesn’t have to map onto a file or a folder, or some other sort of static resource, is quite powerful. The URL is just a way of giving instructions to some server, somewhere. Note that in this example, both / and /bookmarks/ go to the same place -- they both activate bookmarks.views.index!

(Rant: In Django, as in most modern frameworks, you have total control over the way your URLs look. People on the web won’t see cruft like .py or .php or even .html at the end of your URLs. There is no excuse for that kind of stuff in the modern era! (Though, putting .php on the end of all your Django URLs, while pointless, is kind of hilarious and super easy.))

Handling those URLs with some basic views
Start the development server:

Fetch “http://localhost:8000/bookmarks/” in your browser. You should get a pleasantly-colored error page with the following message:

What's going on? Recall this line:

If we look in the bookmarks folder, we can see there's a views.py file... but if we look in that file, it's empty! So, our problem is that the URL parsing is going fine, but there is no one listening at the other end of the phone! This ViewDoesNotExist error happened because you haven’t written a function index in the module bookmarks/views.py.

Well, I guess we should do that!

Let's write some views. Open bookmarks/views.py and put the following Python code in it:

This is a very simple view.

Save the views.py file, then go to http://localhost:8000/questions/ in your browser, and you should see that text.

Add a tag view by adding to the views.py file. This view is slightly different, because it takes an argument (which, remember, is passed in from whatever was captured by the regular expression in the URLconf):

Save views.py.

Navigate to. It’ll run the tag method and display whatever tag name you provide in the URL.

Add a little html to the ‘question’ view. For example, wrap the question_id in strong tags and verify that the view is indeed bold!

Add and commit your code. Remember to write a good commit message that explains what changed. (For examples of how not to write git commits, see http://www.commitlogsfromlastnight.com/.)

Part 3: Models, our database, and making it visible
Introduction to databases and the ORM, or: finally, something we couldn't've done with plain HTML/CSS/JS!

Creating a basic model, in models.py

Creating tables (carefully, with South)

Add data to your app via the command line

Database migrations and South, part 2

Modify views and templates to use model data

Part 4: Reusing others' apps
Users and authentication

CRUD with Django forms

Part 5: AJAX and style time
Adding and updating bookmarks with JSON and asynchronous Javascript

(sync up here)

Time to make our CSS and/or JS more awesome!

Part 6: Sharing with others
Surfing to classmates' "runserver" instances

Deployment on Heroku

Sharing on Github


 * Rename origin to upstream
 * Create a fork
 * Do a push

Brief discussion of other deployment options

Part 7: Exercises for the reader
Writing your own tests

Write your own styles / JS frontend behavior

Handling user-uploaded media

Accessing a Django-powered API (Tastypie)

Learn about regular expressions (those crazy things we used in URLs)

Learn about relational databases