Pythonize Me: how to manage caller context variables in Python? (Python/Django)
django, django-context, python
Solution
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:
class MyView(object):
def __call__(self, request, slug)
# do stuff here
def helper_method(self):
# etc.
Then you can name the class in your `urls.py` file, and it will be called like any other python function.
Doing this also lets you turn similar views into object instances:
class MyView(object):
def __init__(self, parameters):
# initialize instance
def __call__(self, request, slug):
# main view code goes here
first_view = MyView("some parameter")
second_view = MyView("some other parameter") # creates second object instance
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
Problem
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?