DRY your views with middleware
When I have Django URL patterns like:
urlpatterns = patterns('',
(r'^(?P<foo_id>\w+)/$', 'myproject.myapp.views.show'),
(r'^(?P<foo_id>\w+)/edit/$', 'myproject.myapp.views.edit'),
(r'^(?P<foo_id>\w+)/delete/$', 'myproject.myapp.views.delete'),
)
I always end up with views like:
def show(self, foo_id):
foo = get_object_or_404(Foo, id=foo_id)
...
def edit(self, foo_id):
foo = get_object_or_404(Foo, id=foo_id)
...
def delete(self, foo_id):
foo = get_object_or_404(Foo, id=foo_id)
...
Having the same few lines at the top of every function in makes me feel dirty.
You can clean this up with a Middleware class, replacing
foo_id
with the actual object before calling the view.
myproject/myapp/middleware.py
looks like this:
from django.shortcuts import get_object_or_404
from someapp.models import Foo
class FindObjects:
def process_view(self, request, view_func, view_args, view_kwargs):
if 'foo_id' in view_kwargs:
foo_id = view_kwargs['foo_id']
view_kwargs['foo'] = get_object_or_404(Foo, id=foo_id)
del view_kwargs['foo_id']
I include it in settings.py
:
MIDDLEWARE_CLASSES = (
...
'myproject.myapp.middleware.FindObjects',
)
And now my views look like this:
def show(request, foo):
... yay, do stuff with foo ...
Very useful for views with many parameters, or views with multiple optional parameters. In one project, I have views which process data for three different situations: data in a metropolitan area, data in a city, or data in a city within a metro. My middleware for that looks like this:
from django.shortcuts import get_object_or_404
from phuce.metros.models import City, Metro
class FindObjects:
def process_view(self, request, view_func, view_args, view_kwargs):
city = metro = None
if 'metro_link' in view_kwargs:
metro_link = view_kwargs['metro_link']
metro = get_object_or_404(Metro, link=metro_link)
del view_kwargs['metro_link']
view_kwargs['metro'] = metro
if 'city_link' in view_kwargs:
city_link = view_kwargs['city_link']
if metro:
city = get_object_or_404(City, metro=metro,
metro_link=city_link)
else:
city = get_object_or_404(City, link=city_link)
del view_kwargs['city_link']
view_kwargs['city'] = city
It’s much tidier without that monster in my views.