I have found it a mystery why everything in the [Django documentation]http://docs.djangoproject.com/en/dev/topics/http/middleware/) always mentions how important it is to order middleware correctly, and yet no canonical order is given for the supplied middleware. The following ordering is what I have settled on after a long conversation and exchange with some folks in #django on freenode.

# Define our middleware classes.
# To disable caching for devel, use simple://.
MIDDLEWARE_CLASSES = (
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.middleware.gzip.GZipMiddleware',
    'django.middleware.cache.CacheMiddleware',
    'django.middleware.http.ConditionalGetMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.doc.XViewMiddleware',
)

Of course, I bet you want some explanation as to why this is the right order. I'll give it my best shot.

Session middleware needs to come before Auth middleware, because authentication is handled with sessions. Django needs to look up the session of a user before the identity of a user can be looked up.

Both of these come before Cache middleware so the CACHE_MIDDLEWARE_ANONYMOUS_ONLY setting is honored. If sessions and authentication are not established first, then Django will throw an error in your webserver log insisting you have authentication middleware installed.

I don't really know what XView does, so it is last. It isn't that important.

Common middleware can go near the bottom in my setup. If you wanted to use the vary_on_cookie decorator, then it would need to go much higher in the list.

Conditional Get middleware needs to see Etags, so it must be above the Common middleware that sets those.