Sometimes We want to expose part of the Django admin site to the user. Django provides a way to build those admin site page URLs symbolically using the built in URL reversing system, using the reverse function. This feature is well documented, but sometimes hard to find. The correct url is here, on reversing admin URLs.

I finally get around to setting up a django development environment on my MacBook Pro running Lion. I immediately run ino the error “Could not call install_name_tool” error when I try to run mkvirtualenv

The solution is very simple (and silly). We always remember to install XCode before setting things up. But by downloading and “installing” XCode from the AppStore only download and install the XCode Installer. You have to run the downloaded installer to get XCode install.

Should I upgrade my Django application to the current version? The very short answer is Yes.

The slightly longer answer is “Yes if your application is more than a static site used by more than 10 people”.

Starts with the general first. Upgrading an application that is already in production is always a hard decision. What are general pros and cons?

Cons

Cost — time and money. Someone has to (be paid) to do the work.

Break something — for a non trivial update, chances are you have to make some code changes. When you touch the code, you may break something. To make it worst, what if the original developers are gone?

Dependencies — if your application uses other third party software, have they upgraded? If they are incompatible with the new version, it will break.

Pros

New Features — The availability of a new feature on it’s own is not a good enough reason for upgrading. “The site works now, why change?” A developer may want to try out a new feature on a new release. But it has to have real benefit to the application to make this a Pro instead of a Con.

Speed Improvemence — platform vendors often upgrade a platform to improve performance. This is often a legitimate reason for upgrading.

Avoid obsolescence — This point applies especially to web frameworks. The web environment changes quickly. Platform provider may choose to end support for older versions quickly.

Security — This point also applies especially to web frameworks. New attacks are being develop every day. Beyond small emergency security fixes, a framework may add new security feature that is useful.

Let’s focus on Django. Speaking from real world experience, we have upgraded production django sites from 1.1 to 1.2 to 1.3 each time a new release comes up. Our reasons for upgrading are driven primarily by new features that we can use. Our sites are all transactional in nature. The more sophisticated the site, the more of a reason to upgrade.

New Features We Like: Working backwards from the current 1.3 release:

Django 1.3 Features that we like

Support for lookups spanning relations in Django admin’s list_filter option — this makes list_filter actually useful. Often with a large object hierarchy it only make sense to use list_filter to limit/segment the data at the top levels of the hierarchy.

Unittest2 — The new unittest2 test support is now provided within Django 1.3 even if you are running an older release of python. Many features in unitest2 helps you write tests faster.

How to Convince Your Clients or Management to Upgrade?

“If it ain’t broke don’t fixed it” maybe the response that you are getting. The best approach for us is to roll the upgrade work in with the next release. Initial conversion should not take more than one or two days. If you have a one week or a two weeks software release coming up, add the conversion work to it. That is what we do. And in the mean time, try upgrading on smaller non production sites.

Introduction

If you are using Django for production level application, you will need to use south. Requirement changes, and therefore your data model will change over time. South is a great tool, but it is complicated. You do not want to make a mistake when migrating an application in production. This is a detail look at how it interacts with your application so that you can understand and use it better.

Interaction

South interacts (reads and writes) with four different items in an application. This is the most confusing part to me. The four items are:

models.py — South reads this to determine your current data model.

migrations/*.py — South creates a sub directory inside your app, and creates for you a migration file for each database migration generation. You can also create these by hand, but normally you will let south creates them for you.

south_migrationhistory table in your database — when you install south, it creates it’s own table and use it to maintain states. Specifically it records the state of the database in this table. South assumes the application schema in the database is consistent with what it records in this table.

your application’s schema in your database — south create and update the schema for you according to the database migration generation, which is the ultimate purpose of using south.

Different commands in south interacts with these items differently:

Normal Migration

Let is start with a normal database schema migration, from generation N to generation N+1. There are three steps in the migration:

This diagram shows what are the inputs and outputs to each step. (Note, in step 2 it reads all of the migration files from all previous generations):

Initial Migration

Let’s add the very first step when using south on a new applicatoin. The initial migration obviously does not have any previous south information. So there are still three steps, but the argument passed to schemamigrate is a little different:

This diagram shows what are the inputs and outputs to each step, adding to the previous diagram:

Converting an Application

Converting an application is a little different because the database schema and the models are already in sync. Somehow we need to “trick” south into creating the other two items, the migration file and the migrationhistory table entry. We also need to deal with the conversion on the first instance vs other instances differently. For the first instance you will create the migration file, and for all other instances you will use the migration file to simply create the migration history table entry.

On the first app instance:

1. Run manage.py convert_to_south app_name to create the migration
file for generation 1, and also to create the migrationhistory entry.

On other app instances:

1. Run manage.py migrate app_name 0001 --fake to create
the migrationhistory without changing the database schema.

Diagram:

Testing and Trying Migration before

There are several different things you can do to “dry run” your migrations.

Schema Migration Generation Test Run

./manage.py schemamigration my_app_name --auto --stdout

The -stdout argument will have South generate and print out the migration code on the console instead of writing it out to the migrations directory. You can do this before you do the actual database migration schema generation. Note that schemamigration only creates the next migration script in the migrations directory. Worst case is you can just delete that file if you decided the migration schema is not needed.

Migration Dry Run

The migration operation can also be tested before actually running to migrate a database:

./manage.py migrate myapp --db-dry-run

This will run the migration except the database is not changed, and the migration is not recorded in the history table in the database.

Useful Commands

Another useful command is the list command. It shows all the migrations defined in the migration files, and whether they have been applied (by reading the migrationhistory table entries):

manage.py migrate --list

Deleting Migrations

Sometime I need to reset a migrated environment. This is particularly useful during initial development of an app. This special command, migrating to the “zero” state, will remove all migration history in the database, but leaving any migration files intact.

Django provide a nice mechanism to report error in its “batteries included” goodness. You can easily setup the Django environment so that it will send you an email when a “server error” occurs. You just need to make sure the following is setup:

Outbound email working

The django environment must be able to send outbound emails. The actual requirement depends on your server environment, but you definitely need to have correct values setup for:

Reference

This is a very common usage pattern. You have a list of items for display, perhaps a list of tags. The list can have zero, one or more items. How do you, using the Django template language, put commas between each item?

1. This simple way will not produce good result for a list of one item:

I gave a short presentation on Django to the Cambridge Python Users group earlier. Nate has a great writeup of the event and the other presentations that evening. I just want to share the slides here. The slides are just visual reminders and do not stand on their own. If you want more info free feel to shoot me an email.

I switched from J2EE to Django as my sole web application platform two years ago and has not looked back since. It allows me to develop, and more importantly maintain, web apps faster and better. It is more time and cost effective for my customers and I.