我正在尝试在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,因为现在有两种不同的方式来访问变量:xyz
和contextDict['xyz']
。并且你必须在电话N
中使用一个,并在堆栈中使用下一个电话N+1
。
c。暴力将所有变量传递给每个函数调用并返回相关的变量。当涉及到很多变量时,这会非常繁琐。
d。在C ++ / C#中,我只需创建一个类MyComplexViewContext
,定义所有共享变量,并创建成员函数来执行工作。然后,您可以将self.xyz
用于该类中的所有内容。
我想我也可以在Python中使用这个方法。不确定这是否是最佳方式。
您对在Python / Django中执行此操作的首选方法有何看法?
答案 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,我没有经验)。