I’m trying to refactor a fairly hefty view function in Django. There are too many variables floating around and it’s a huge function.
Ideally, I want to modularize the view into logical functions.
However, I have to pass the function context around to get easy access to the variables.
For example:
def complex_view(request, slug):
some complex logic which creates variable abc ...
...
some more complex logic which uses variable abc ...
...
etc.
Should become something like:
def complex_view(request, slug):
process_X()
...somehow pass variables and context to next function...
process_Y()
...
etc.
def process_X():
...
def process Y():
...
I can think of a few ways to do this, some of which were pointed out in this page:
http://mail.python.org/pipermail/tutor/2009-February/067506.html
a. Subfunctions defined in the master view. This seems kludgey since it’s hard to tell which variables are shared and which aren’t.
b. Passing locals() in as a dictionary. This is also kludgey because there are now two separate ways of accessing a variables: xyz and contextDict['xyz']. AND you have to use one in call N, and the next in call N+1 on the stack.
c. Brute force pass in all variables to each function call and return relevant vars. This gets very tedious when there’s a lot of vars involved.
d. In C++/C#, I would simply create a class MyComplexViewContext, define all the shared variables, and create member functions to carry out the work. Then you can use self.xyz for everything inside that class.
I suppose I could use this method in Python as well. Not sure if this is the best way though.
What’s your take on the preferred way to do this in Python/Django?
I like (d) – Create a class for it, and use member functions to do the work.
In Django, a view is just a ‘callable’ that accepts an HTTPRequest object, and whatever other paramaters your URL routing passes to it.
Python classes can be callable just like functions, if you define a
__call__method on them, like this:Then you can name the class in your
urls.pyfile, and it will be called like any other python function.Doing this also lets you turn similar views into object instances:
and in urls.py, reference the objects (rather than the class) — the objects can be called like functions as well.
Other tricks are to use inheritance to define similar views, or to provide some general functionality for a number of similar views in a base class, which specialized view classes then inherit from.
You can see this slideshow by Simon Willison for more details, or this snippet for a concrete example