views:

140

answers:

3

Hi, I have the view function in django that written like a dispatcher calling other functions depending on the variable in request.GET, like this:

action = ''
    for act in ('view1', 'view2', 'view3', 'view4', ... ):
        if act in request.GET:
            action = act
            break
...
if action == '':
    response = view0(request, ...)
elif action == 'view1':
    response = view1(request, ...)
elif action == 'view2':
    response = view2(request, ...)
...

The global dispatcher function contains many variable initialization routines and these variables are then used in viewXX functions. Also some initialization code depends on what action is being called.

So I feed that this is bad view design but I don't know how I can rewrite it?

+3  A: 

Instead of sending a request to http://mysite.com/path/to/url?action=view0 and using urlpatterns like this:

urlpatterns = patterns('', 
    (r'^/path/to/url', 'myapp.views.dispatch'),
)

You could send your requests to http://mysite.com/path/to/url/view0 and use urlpatterns like this:

urlpatterns = patterns('', 
    (r'^/path/to/url/view0', 'myapp.views.view0'),
    (r'^/path/to/url/view1', 'myapp.views.view1'),
    (r'^/path/to/url/view2', 'myapp.views.view2'),
    ...
)

And then have each of the sub views call an initialize function to get the common variables.

Whether or not this is bad design depends on what you're doing. In some cases, having a dispatcher makes more sense than splitting everything out.

Seth
Thank you Seth, but what if initialization procedure must be slightly different depending on the action?
dragoon
In that case, you could factor out the common elements of the initialization into one function and keep the unique elements in each sub view. Or, parameterize your initialization function. Depends on the specifics.
Seth
A: 

A much better solution would be to use middleware. The process_view middleware classes are called just before a view is executed, and are passed the view function to be called as a parameter. The middleware can either short-circuit the process by returning an HttpResponse itself, or return nothing to let the view be called normally.

So you could define your URLs in a URLconf as normal, but intercept the calls in the middleware and do your initialisation there, calling the relevant view manually and returning the response directly from the middleware.

Daniel Roseman
+1  A: 

You want a dispatch dict:

actions = {
  '': view0,
  'view1': view1,
  ...
}

response = actions[action](request, ...)

This requires the function signatures to be the same, or use * and **.

Ignacio Vazquez-Abrams
Thanks, this will be very nice solution if I will stick to the dispatcher design
dragoon