Pythonize Me:如何在Python中管理调用者上下文变量? (Python的/ Django的)

时间:2010-01-11 21:06:27

标签: python django django-context

我正在尝试在Django中重构一个相当重要的视图函数。浮动的变量太多了,这是一个巨大的功能。

理想情况下,我想将视图模块化为逻辑函数。 但是,我必须传递函数上下文以便轻松访问变量。

例如:

def complex_view(request, slug):
    some complex logic which creates variable abc ...
    ...
    some more complex logic which uses variable abc ...
    ...
    etc.

应该变得像:

def complex_view(request, slug):
    process_X()
    ...somehow pass variables and context to next function...
    process_Y()
    ... 
    etc.

def process_X():
    ...

def process Y():
    ...

我可以想到几种方法,其中一些方法在本页中指出: http://mail.python.org/pipermail/tutor/2009-February/067506.html

a。主视图中定义的子功能。这看起来很糟糕,因为很难分辨哪些变量是共享的,哪些变量不是。

b。locals()作为字典传递。这也是kludgey,因为现在有两种不同的方式来访问变量:xyzcontextDict['xyz']。并且你必须在电话N中使用一个,并在堆栈中使用下一个电话N+1

c。暴力将所有变量传递给每个函数调用并返回相关的变量。当涉及到很多变量时,这会非常繁琐。

d。在C ++ / C#中,我只需创建一个类MyComplexViewContext,定义所有共享变量,并创建成员函数来执行工作。然后,您可以将self.xyz用于该类中的所有内容。    我想我也可以在Python中使用这个方法。不确定这是否是最佳方式。

您对在Python / Django中执行此操作的首选方法有何看法?

2 个答案:

答案 0 :(得分:10)

我喜欢(d) - 为它创建一个类,并使用成员函数来完成工作。

在Django中,视图只是一个“可调用的”,它接受一个HTTPRequest对象,以及你的URL路由传递给它的其他参数。

Python类可以像函数一样调用,如果你在它们上定义__call__方法,就像这样:

class MyView(object):
    def __call__(self, request, slug)
        # do stuff here

    def helper_method(self):
        # etc.

然后你可以在urls.py文件中命名该类,它将像任何其他python函数一样被调用。

这样做还可以将类似的视图转换为对象实例:

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

并在urls.py中引用对象(而不是类) - 对象也可以像函数一样被调用。

其他技巧是使用继承来定义类似的视图,或者为基类中的许多类似视图提供一些通用功能,然后专用视图类继承。

您可以查看this slideshow by Simon Willison了解更多详情,或this snippet了解具体示例

答案 1 :(得分:0)

我建议使用类似于d)的东西,如下:

class ComplexView_SharedVariables:
  # Shared variables (to be used as instance variables, not class variables!)
  a = "somevalue"
  b = ...
  c = ...

class ComplexView_Methods1:
  ... some functionality ...

class ComplexView_Methods2:
  ... some more functionality ...

class ComplexView_All(ComplexView_SharedVariables, ComplexView_Methods1, ComplexView_Methods2):
  # This class puts together all functionality and shared variables
  pass

使用此过程,您甚至可以将类拆分为不同的文件(如果可以使用Django,我没有经验)。