///TITLE///
Jono Bacon wraps up our Django series with some pro tips for common problems.

///HEADLINE///
Introduction To Django: Part 4

///NAME///
Jono Bacon

///COPY///
Over the last three parts in this series about getting started with Django we have explored many of the core underlying principles of how you create a powerful dynamic web app. We have covered setup, databases, models, forms, setting up URLs, templates, theming and more.

In this fourth and final article we are going to fill in some of the gaps in the content we have previously covered and delve into some tips and tricks that you will likely need to know in your day to day Django programming. This article presumes knowledge of the basics of many of these areas, and I will show you some solutions to some common tasks that we have not yet covered in the series so far.

// More Templating Fun

In a previous article we explored how to use Django templates to lay out the user interface for your web pages. When we covered this we looked at the basics, but a strong knowledge of Django's templating language will help you to produce better, more customized user interfaces in your application.

There are two primary areas you will need to know well when writing templates: looping and conditionals.

We have already covered looping with a 'for' loop:

	{% for i in content %}
		{{ i }}
	{% endfor %}

Typically when you send data to a template from your view you are sending a collection of items that you generated with a query such as with:

	content = MyTable.objects.all()
	return render_to_response('mytemplate.html', {'content': content}, context_instance=RequestContext(request))

When sending data like this you can iterate through it using the 'for' loop syntax above. Sometimes though you may want to have more control over the kind of data that you send the template.

As an example, throughout many Python programs you will want to represent data structures in different ways. When running a query such as the one above, you get a list of items which makes it easy to iterate through. Sometimes though you may want to use a dictionary such as:

	{ "one" : 1, "two" : 2, "three" : 3 }

When working with this kind of data structure you would generate it in your view and then send it to the page in the same way. As a simple example:

	content = [ "one" : 1, "two" : 2, "three" : 3]
	return render_to_response('mytemplate.html', {'content': content}, context_instance=RequestContext(request))

Iterating through this in the template is a little different though. To do this we use this format:

	{% for k, v in content.items %}
		<p>The key is {{ k }} and the value is {{ v }}</p>
	{% endfor %}

There are a few things to note here. The first is that we use '.items' at the end of the content that we are iterating through; this pulls out the times inside the data structure. We then pull out two items as this is a dictionary, and as such 'k' refers to the key and 'v' refers to the value.

Sometimes you may want to be even cleverer and have a list of dictionaries such as this:

	content = [{ "one" : 1, "two" : 2 }, { "three" : 3 }, { "four" : 4 }]

To iterate through this we need to first create a loop that iterates through the outer list and then inside that we iterate through each dictionary and pull out the values:

	{% for item in content %}
		{% for k, v in item.items %}
			<p>The key is {{ k }} and the value is {{ v }}</p>
		{% endfor %}
	{% endfor %}

Another common use case is when you want a dictionary of dictionaries. An example of this is when you are building a collection of data that relates to something. As an example:

	content = {
		"bob" : { "job" : "Programmer", "id" : 234 },
		"jane" : { "job" : "QA", "id" : 245 },
	}

Here we have a dictionary for each person and inside the dictionary are different pieces of information about that person. Also notice how we are using the same key (e.g. "job") in each dictionary. Later we will explore how to use conditional statements on these kinds of structures, but lets first iterate through it:

	{% for name, info in content.items %}
	<h1>{{ name }}</h1>
		{% for k, v in info.items %}
			<p><strong>{{ k }}</strong> : {{ v }}</p>
		{% endfor %}
	{% endfor %}

Here we have our outer for loop that iterates through the names and pulls that data out as 'name' and 'info', and then the inner loop iterates through the dictionaries that are in 'info'.

Another common scenario that you will find yourself in at some point is creating a data structure like this that combines data from your Django models and other data mixed together. As an example, imagine we have a People table and we want to set additional data in our data structure. This is how you would create it in the view:

	people = People.objects.all()

	content = {}
	for person in people:
		if person.clearance == 1:
			content[person] = { "building" : "HQ", "knowssecrets" : True }
		else:
			content[person] = { "building" : "office", "knowssecrets" : False }
			
	return render_to_response('mytemplate.html', {'content': content}, context_instance=RequestContext(request))

Here we are using a data object as the key in our outer dictionary and the value is our defined dictionary. As an example, if we have an entry in People called "Bob" and he has clearance, our data structure will look like this:

	{ <People: Bob> : { "building" : "HQ", "knowssecrets" : True } }

Iterating through this is similar to our previous example, but we can reference the fields inside the data object. As an example:

	{% for name, info in content.items %}
	<h1>{{ name.fullname }} has clearance level {{ name.clearance }} </h1>
		{% for k, v in info.items %}
			<p><strong>{{ k }}</strong> : {{ v }}</p>
		{% endfor %}
	{% endfor %}

You should find that these examples will cover most of the scenarios you face when iterating through different types of data in your templates.

// Conditionals and Filters

Let's now switch gears and start looking at conditional statements in Templates. Conditional statements are used to check if different values equate to other values and based upon the response we can display different information.

As an example, image we have this kind of structure in our view:

	content = [ "admin", "bob", "jane" ]

Here we have a simple list of names. In our template we can now use the 'if' template command to check if the admin is in the lost and display different content:

	{% for name in content %}
		{% if name == "admin" %}
			<p>Admin logged in</p>
		{% else %}
			<p>Normal user logged in</p>
		{% endif %}
	{% endfor %}

Another nice way of doing this is to use the 'ifequal' command:

	{% for name in content %}
		{% ifequal name "admin" %}
			<p>Admin logged in</p>
		{% else %}
			<p>Normal user logged in</p>
		{% endifequal %}
	{% endfor %}

Another nice feature of Django templates are the wide range of filters. As an example, a common scenario is that you will want to display a table full of rows of information from your database, but you will want to display something such as "no records" when there are no rows.

A good approach to this problem is to use the 'length' Django filter. As an example, imagine we want to display the list of users from our People table. Here is how we could check if there are entries and display the appropriate content:

	{% ifequal content|length 0 %}
		<p>No people.</p>
	{% else %}	
		{% for name in content %}
			{% ifequal name "admin" %}
				<p>Admin logged in</p>
			{% else %}
				<p>Normal user logged in</p>
			{% endifequal %}
		{% endfor %}
	{% endifequal %}

Here we use a normal ifequal statement, but we apply the 'length' filter to the content variable with the '|' symbol.

There are a number of useful filters available in Django. Let's a look at some of the most popular.

Firstly you may want to filter dates in different ways, such as detecting the user's locale and filtering the date in the right way based upon their location (e.g. 1-11-2013 as opposed to 11-1-2013). Here you can apply the date filter to a datetime object:

	{{ value|date:"D d M Y" }}

This would format it like this: Tue 08 Feb 2013. The letters in the string determine the way in which the date is formatted and there are many different options for formatting the date in pretty much any way you want.

Another useful filter is 'dictsort' and 'dictsortreversed' that sorts the dictionary that the filter is applied. 'first' and 'last' are also useful filters for returning the first and last items in a list. For a list of other useful filters, see the 'Template Filter Cheatsheet' box.

# Adding Custom Django Commands

Throughout your experience of using Django you will have become intimately familiar with using the 'manage.py' script that comes with your project. You most commonly use this to run commands such as:

	python manage.py syncdb
	python manage.py runserver

manage.py is the swiss army knife that comes with Django. It contains commands to do all kind of things; create apps, set up tests, validate your models, inspect your database and more.

Sometimes though you may want to create your own custom commands that can be called with manage.py. An example of this is when you need to trigger functionality in your Django project from a seperate non-Django project.

As an example, a project that I started some time ago was the Ubuntu Accomplishments project; a system for detecting when you achieve different things and awarding you trophies for those achievements. As part of the project I wrote a validation server that checks these trophies to protect against scrupulous users faking their trophies. Some time into writing the validation server I needed a way to visualize failures and problems that the server detected. As such I got to work writing a Django front-end for this.

I then faced a challenge: when the validation server detected a failure, how was it going to add a record to the Django database so that the Django front-end would see it? On one hand I could update the database manually by directly connecting to it, but this seemed a messy and hackish approach. I then learned I could create a custom manage.py command to do this. As such I created an 'addfailure' command and the validation server simply called this command when there was a failure and pass to the command the failure details. Let's now explore how to create one of these commands.

These different manage.py commands are broken up by application. You can create a set of commands for each application within your project. As an example, let's assume that we have a Django project for storing a list of employees in a company. As part of this project we have a model called 'Staff' that stores the list of employees. Let's also assume that the application within the project is called 'company'.

Each of the custom functionality that relates to the manage.py script is referred to as Management. To get started we need to first create a "management" directory inside our application (as such in "company/management"). Inside that directory we then need to create a "commands" directory that will store each of our commands (in this case we create "company/management/commands".

Let's now create a custom command called "addstaffmember". To do this create a file called addstaffmember.py inside the commands directory. We also need to an empty file called __init__.py in that directory.

Now edit addstaffmember.py and let's add some code to it.

We first need to load some modules that we use for implementing a command:

	from django.core.management.base import BaseCommand, CommandError

Now we create a new class called Command that is of the BaseCommand type and add a single 'handle' function that we will use to store our command logic:

class Command(BaseCommand):
        def handle(self, *args, **options):
                print "hello world"

Save the file. Fortunately, Django is smart enough that it automatically registers any command in the commands directory that doesn't start with an underscore. As such, you can run 'python manage.py' and you should see your command listed.

Something we should first add for completeness is a short help string that explains what this command does. This string will be displayed when someone runs 'python manage.py help addstaffmember'. To do this add this add the 'help' line after the class definition:

	class Command(BaseCommand):
		help = 'adds a staff member to the database'

In our current form our command is not particularly useful. We need to be able to accept a set of arguments to our script that we can then process and add to the database. We first need to specify the arguments we are taking, and we can do this by specifying the 'args' variable in much the same way we specified 'help'. Inside the args variable we specify the names of the different arguments we will take. As an example:

	class Command(BaseCommand):
		args  'firstname lastname job'
		help = 'adds a staff member to the database'

Now if we run 'python manage.py help addstaffmember' you can see that the help string and list of expected arguments are listed.

Although we specified these arguments, these argument names don't map directly to variables in our script. We instead need to read in the argument position and assign them to variables. For example:

	item_firstname = args[0]
	item_lastname = args[1]
	item_job = args[2]

Now we have our data read in, we can now add the data to the database. First we need to load our model:

	from company.models import Staff

We can now create a new Staff entry in which we pass it the data from our variables and save it to the database:

	entry = Staff.objects.create(firstname=item_firstname, lastname=item_lastname, job=item_job)
	entry.save()

Our command is now complete! We can test it like this:

	python manage.py testcommand "Alan" "Cox" "Kernel Programmer"

When we run this our Staff table will be updated and you should it see it in your project! Here is the complete command script:

	from django.core.management.base import BaseCommand, CommandError
	from company.models import Staff

	class Command(BaseCommand):
		args = 'firstname lastname job'
		help = 'Adds a staff member to the database.'

		def handle(self, *args, **options):
		        item_firstname = args[0]
		        item_lastname = args[1]
		        item_job = args[2]

			entry = Staff.objects.create(firstname=item_firstname, lastname=item_lastname, job=item_job)
			entry.save()

// Understanding Your Models

Like most people new to Django, your first few projects will have just a few models as you pick up the system. As your projects turn from sample applications to full blown applications that you want others to use, your models will grow and expand. Before long you will have a comprehensive set of inter-related models, and as your design and functionality changes, so will your models. You will end up refining your models step by step with the hopes of finalizing the design so that you don't have to change them all that much when your project is live.

You will then be faced with the likely prospect of wanting to perform a full review of all of your models to ensure you don't have any nonsensical relationships before you finally release. The challenge here with a lot of inter-connected models is getting a good overview with so much complexity.

This is when it is useful to have a graph of all of your models and these interconnections. Fortunately, you don't need to sit down with paper and a pen to draw this graph; we can generate it automatically.

To do this you will need to install the Django Extensions. This is a collection of useful additions to the functionality in manage.py that we can use. This should be packaged for your distribution (as an example, I installed python-django-extensions in Ubuntu). You can also grab the code directly from https://github.com/django-extensions/django-extensions.

To use the extensions you will need to ensure that they added as an application your project's settings.py in the INSTALLED_APPS section. Add the following to INSTALLED_APPS:

	django_extensions

The way in which the graphing works is that you run a command that generates a GraphViz schema for your models; this is a special mark-up language used for generating graphs. Usually you then use another tool to convert that schema into a graph that you can view. Fortunately we can do this all in one command by running:

	python manage.py graph_models company -a -g -o my_project.png

Here we are running the graph_models command on the company application and generating a file called my_project.png that contains our graph. An example of such a graph is shown in Fig 1.

# Wrapping Up

I know many of you have been tracking this series, and I want to thank you for sticking along with me for the ride. Django is an absolutely fantastic framework for building powerful web applications with the power, extensibility, and pleasure of using Python to write these apps.

We have covered a lot of content along the way, but of course there are many other topics still yet to explore. I recommend immersing yourself in the fantastic documentation available at https://docs.djangoproject.com/en/ and be sure to ask questions online on a site such as http://stackoverflow.com/ and use the Django tag. Another great source of help is the #django channel on the Freenode IRC network.

Good luck with your future projects and be sure to let me know how you are getting on! Enjoy!

/// BOX TITLE///
Template Filter Cheatsheet

{% spaceless %}			Removes spaces between HTML tags.
{% ssi '/home/jono.foo.html' %}	Includes the content of the specified file on the page.
{{ value|addslashes }}		Add slashes before the quotes.
{{ value|capfirst }}		Capitalize the first character.
{{ value|cut:" " }}		Removes all instances of the specified character from the value.
{{ value|default:"nothing" }}	The if the default value is False, use the specified value.
{{ value|filesizeformat }}	Formats a file size in human readable form (e.g. 2.1 MB).
{{ value|floatformat }}		Changes how floats are displayed (you can apply additional formatting to this).
{{ value|length_is:"4" }}	Returns true if the value has the length specified.
{{ value|linenumbers }}		Displays the value with line numbers.
{{ value|lower }}		Converts the string to all lowercase.
{{ value|time:"H:i" }}		Formats time in the given format (in this case 01.30).

See the full list of filters in the documentation at https://docs.djangoproject.com/en/dev/ref/templates/builtins/

/// BOX TITLE///
Migrating Between Models With South

Some of you may be a little worried about what happens when you release your Django web application and then discover that you need to change the structure of your models. What will happen to all that data when the database structure changes?

Fortunately there is a great solution to this problem in the form of South.

South is a project that plugs into Django that allows you to change models.py and then generate a "migration". This is a file that will convert the database over to the new models and migrate the data over. This provides a safe way of changing your underlying database structure.

This is the recommended way in which you manage your database when you have production code out there. You can find out more about south at http://south.aeracode.org/.

///PIC///
fig1.png

///CAPTION///
The graphs show the interconnected relationships neatly.

///PIC///
fig2.png

///CAPTION///
The Django documentation is fantastic for learning different parts of the platform.

///PIC///
fig3.png

///CAPTION///
Be sure to post your questions on stackoverflow.com with the Django tag.

///END COPY///

///BIOG BIT///
Jono Bacon is the Ubuntu Community Manager, author of The Art Of Community, and founder of the annual Community Leadership Summit.
