DRY your views with middleware

On August 11, 2007 in development, django, python

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:
      view_kwargs['foo'] = get_object_or_404(Foo, id=view_kwargs['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 = get_object_or_404(Metro, link=view_kwargs['metro_link'])
      del view_kwargs['metro_link']
      view_kwargs['metro'] = metro
    if 'city_link' in view_kwargs:
      if metro:
        city = get_object_or_404(City, metro=metro, \
                                 metro_link=view_kwargs['city_link'])
      else:
        city = get_object_or_404(City, link=view_kwargs['city_link'])
      del view_kwargs['city_link']
      view_kwargs['city'] = city

It’s much tidier without that monster in my views.

29 comments Add yours…

Italo Maia, 9 months ago

Cool! o!

James, 9 months ago

Brilliant work! This helps me understand middleware more.

keep it up!

Favo, 9 months ago

Decorator is more flexible, you can have different helper decorators for the generic stuff.

{{{
@prepare_foo
def show(self, foo):

}}}

Nathan Ostgard, 9 months ago

Good idea, Favo. I didn’t think of using a decorator.

Amirouche B., 8 months ago

@Favo, what do you mean by “different helper decorators for generic stuff” could you give an example ?

Nathan nice, I was lookinf for something like for some time now :)

Amirouche B., 8 months ago

I looked at the decorator idea, pretty cool. I have a snippet on my blog http://ephemerebits.blogspot.com/2007/08/network-effet-in-practice-custom-urls.html

forum, 4 months ago

I had a similar idea about using a field to create an in-between ‘removed’ state. Your method of achieving this is much more cleaner than I imagine mine would have been. Good job!

Alex, 2 months ago

Found it rather interesting.

felsefe, 2 months ago

Looks very interesting.
Thanks for sharing.

kevin, 2 months ago

Excellent Idea! thanks for sharing!

edebiyat, 2 months ago

Great! This helps me understand middleware more.

cesare pavese, about 1 month ago

Thanks, this helps me understand middleware more.

Jo Presse, about 1 month ago

Nice, i have install it!

Go get em guys

Rrobert Johnson, about 1 month ago

That’s really great. and even was helpful

siyaset, about 1 month ago

Looks very interesting..
thanks…

filozoflar, about 1 month ago

Very good article!

sinema, about 1 month ago

Excellent, thanks for sharing!

kykladen, about 1 month ago

Very good Nathan, I helps me to improve my middleware.

Malcott, about 1 month ago

well done!
thanks for sharing

Clint, 27 days ago

Great idea! I was looking for something like this. Thanks for sharing

Webdesign, 22 days ago

Very good article!

Suchmaschinenoptimierung, 22 days ago

Nice article, thank you very much.

Suchmaschinenoptimierung, 22 days ago

Nice article, thank you very much.

Webwork, 22 days ago

wow amazing , really great. thanks a lot guys.

Annem Dizisi, 22 days ago

Nice article, thanks.

Chartfon, 22 days ago

Thanks guys. nice article.

Paul, 21 days ago

Nice tip. Thanks for sharing.

Games, 19 days ago

Nice tip , thanks

kuaför malzemeleri, 5 days ago

well i guess there s something wrong with the code or i did not have latest libraries
lcd tv | satılık ev

Post a comment