The Problem

Changing specs.

No specs.

Tight schedules.

You need to get things done fast.

Solution

djangodesktop-800x600.jpg

Yeah but

I'm not a Django newbie anymore.

I get annoyed with Django sometimes.

It's still better than PHP - but there are parts I wish I could change.

Following are some tips, techniques and tools that have kept me happy with Django.

YMMV

The Tutorial Lied to You!

The tutorial is a great way to learn Django! Unfortunately in the interest of brevity it contains some less than optimal code.

First a few obvious points.

settings.py

Don't hard-code paths!

# Suggested settings generated by django-admin.py
TEMPLATE_DIRS = ("/home/html/django_templates",)
MEDIA_ROOT = '/home/media/media.lawrence.com/'
# Better - especially if test and deployment are
# on different boxes
import os
DIRNAME = os.path.abspath(os.path.dirname(__file__))
TEMPLATE_DIRS = (DIRNAME + "/templates",)
MEDIA_ROOT = DIRNAME + '/media/'

Don't reference projects

# Including apps in settings
INSTALLED_APPS = (
  ...
  'mysite.polls'
)
# And in views.py or admin.py
from mysite.polls.models import Poll

Or get used to naming all your projects "mysite"

Your project directory should be on the PYTHONPATH

3rd party apps should live somewhere other than the root of your project folder.

The Tutorial teaches bad habits

The Django tutorial basically teaches you to write templates and views and how to use the ORM.

My first few Django apps were mostly django templates and python code handling querying and request processing in the views - just like the tutorial.

Real World Projects require Testing

Unfortunately - views are the hardest part of my code to test.

Big complicated views are a bad code smell in Django!

Query logic belongs in a Model manager

Data processing code belongs in a form class

Missing pieces

South!

Let's make Django smarter

Most annoying part of Django to work with?

"Django’s template language is designed to strike a balance between power and ease."

Personally, I could use a little more power!

A little logic in a template never hurt anyone

Adding an {% if %} tag implementation that allows operators (<=, >=, !=, in) helps out quite a bit. I like the one in django-sugar which also contains other goodies.

$ pip -E pyenv install -e \
git://github.com/montylounge/django-sugar.git#egg=django-sugar
INSTALLED_APPS = (..
                  'sugar', #Add the app in your settings
                  )
# And if you're really sure you'll always want it
from django.template.loader import add_to_builtins
add_to_builtins('sugar.templatetags.smart_if')

Debugging and Profiling

Rob Hudson's django-debug-toolbar is invaluable.

$ pip -E pyenv install -e
git://github.com/robhudson/django-debug-toolbar.git#egg=debug_toolbar

# Add to installed apps in settings.py and and add middleware
MIDDLEWARE_CLASSES = (
  'debug_toolbar.middleware.DebugToolbarMiddleware',
  ...
  )

# And add
INTERNAL_IPS = ('127.0.0.1',)

Debugging and Profiling

Sometimes we need to step through code.

# Traditionally: add call to pdb near the trouble spot and then
# step through in the console
import pdb;pdb.set_trace()

This frequently annoys me as I lose echo on my console and have to stop, reset, and restart the server. It would be nice to run the debugger in our browser for little things...

Debugging and Profiling

$ pip -E pyenv install werkzeug # prerequisite
$ pip -E pyenv install -e \
git://github.com/django-extensions/django-extensions.git#egg=django-extensions

# Add to installed apps
INSTALLED_APPS = (
    ...,
    'django_extensions',
)

$ ./manage.py runserver_plus

Debugging and Profiling

Lots of other goodies in command_extensions. A few of my favorites:

$ ./manage.py graph_models auth | dot -Tpng -o test.png

Pretty Pictures

test.png

Advanced Profiling

$ ./manage.py runprofileserver --prof-path=. --kcachegrind
$ kcachegrind

To get code paths, execution time, most called functions, etc

Another favorite:

$ ./manage.py shell_plus # auto-imports all Models

And the kitchen sink

command-extensions has

Just stay away from describe_form

But I just want to use Django

http://code.djangoproject.com/wiki/Version1.2Features

South, debug-toolbar, and smarter {% if %} tag are all up for inclusion in Django 1.2

From __future__ import *