CherryPy 应用程序的最佳结构实践有哪些?
我正在写一个cherrypy应用程序,想知道在构建较大应用时,处理程序和代码的最佳结构是什么样的?
我知道可以通过cherrypy.root简单地进行分配,但在编写处理程序和分配它们时,有哪些好的做法呢?
(让我来证明我有多困惑!) 我最初的想法是写一个标准的处理程序类,根据当前的URL或类/方法组合来推断要运行的模板。然后,我会将这个处理程序的一个实例多次分配给不同的路径,以创建页面。不过,我觉得这样做可能不太行,因为递归引用可能会出问题。
所以,考虑到我对自己代码的结构已经感到迷茫,我非常希望能得到一些建议和示例!
如果需要我进一步解释,随时可以问我详细的问题。虽然网上有很多cherrypy的教程材料,但大多数只是表面上的介绍。
2 个回答
CherryPy这个框架特别设计成不需要你从它提供的基础类去继承,这样你就可以自由地设计自己的继承方式,或者更重要的是,根本不使用继承。你当然可以定义自己的基础类并从中继承;这样一来,你就可以通过你类的__init__
方法,以及类级别的变量和方法来统一处理器的构建和配置。
不过,推荐的做法其实是不同的。对于大多数网页应用来说,你并不想改变处理器的实际构建逻辑,也不太关心类级别的变量或方法;相反,你更希望每个URI(统一资源标识符)或者URI的子树,甚至是整个网站都有可重用的变量和方法,而不是每个类都有。你通常是通过实例配置(处理器的元数据)和实例方法(处理器的逻辑)来区分不同的处理器。传统的基于类的继承虽然可以做到这一点,但对于这种定制化来说,效果不是很好。
因此,CherryPy被设计成能够提供这种基于资源集的定制化,而传统的类继承做得并不好。它通过两种方式来实现这一点:1)配置系统的设计,允许你将元数据绑定到单个URI、URI的子树、处理器的子树,或者整个网站,使用相同的语法(可以查看http://docs.cherrypy.org/dev/intro/concepts/config.html了解概况);2)钩子和工具系统,允许你将逻辑绑定到单个URI、URI的子树、处理器的子树,或者整个网站。可以查看http://docs.cherrypy.org/dev/intro/concepts/tools.html。
所以,实际上:你可以在cherrypy.root
上使用普通属性来构建你的处理器树:
def make_app():
root = Root()
root.foo = Foo()
root.bars = BarCollection()
return root
但是,不要让Root、Foo和Bar继承自一个共同的基础类。相反,写一些独立的工具来完成像“推断模板”这样的事情。也就是说,不要这样:
from cherrypy import expose
class Foo(MyAppBase):
@expose()
def index(self, a, b, c):
...
root.foo = Foo(template='foo.html')
而是这样写:
from cherrypy import expose, tools
class Foo(object):
@tools.render(template='foo.html')
@expose()
def index(self, a, b, c):
...
root.foo = Foo()
...其中'tools.render'是你写的一个CherryPy工具,用来查找和应用给定的模板。这种方法可以让你在配置文件中覆盖工具的参数,而不需要重新打包或修改你的代码:
[/foo/]
tools.render.template = 'foo2.html'
这个问题比较主观,但我还是试着回答一下。
首先,数据库和数据代码要和网页代码分开。我通常会在一个叫
DB/
的文件夹里放很多小文件,每个文件里有一个类,然后把它们合并成一个Base.py
文件,比如:Web/ Base.py - The main "base" class, which includes the classes in other web files, starts the web server in
别忘了在每个模块目录里加上__init__
Users.py - The class which includes methods generally from "DB/Users.py" which checks permissions etc before returning (you may wish to add DB-level security later though) ... DB/ Base.py - The main base DB class, includes the other DB classes. Creates new SQLAlchemy/whatever instances and create database schemas if they don't etc. May pay to have database-wide methods here to keep creating connections etc in one place if you decide to change databases later Users.py - The user/password etc DB storage class file ... Templates/ (HTML templates go here) Static/ (Static images/CSS/javscript etc go here)__init__.py
,这样 Python 才能找到子目录里的模块。我认为,代码结构的方法不一定要固定,但要保持一致。我会写一份文档,列出我的命名规则和使用这些规则的理由,并尽量遵循这些规则,直到它们变得不合理为止。不过,正如那句名言所说,
a foolish consistency is the hobgoblin of small minds
,这是引用自 Python 风格文档 :-)尽量使用类,而不是直接用函数。对于小项目可能没什么关系,但对于稍微复杂一点的项目,事情可能会变得棘手。我更喜欢把每个文件的目的明确,只在一个文件里放一个类,除非有多个类放在一起是合理的。
这个观点可能有点争议——我通常会把我的类命名为
Class
,然后通过模块名来引用它。我给你一个Base.py
的例子:
这样可以减少在导入时其他模块相互引用时出现的问题,因为import Users class Base(Users.Class): def
__init__
(self): Users.Class.__init__
(self)from Users import Users
如果Users.py
里有from Base import x
就会冲突,所以我总是通过模块名来引用。这只是个人偏好,所以你可以随意 :-P
希望你能从这篇帖子中得到一些启发。