werkzeug 将 URL 映射到视图(通过端点)
我开始使用werkzeug,想要把网址(来自一个叫urls.py的文件)和视图(来自一个叫views的文件夹,里面有不同的文件来管理不同类型的视图)对应起来。我的文件夹结构大概是这样的:
myapp/
application.py
urls.py
views/
__init__.py
common.py
places.py
...
我的urls.py文件大概是这样的:
from werkzeug.routing import Map, Rule
url_map = Map([
Rule('/places', endpoint='places.overview')
])
而且我在views/places.py文件里有这样的内容:
def overview(request):
mycode...
render_template('places.html', extra...)
大多数werkzeug的例子都展示了如何使用装饰器expose来把网址和视图关联起来。对于只有5、6个网址的应用来说,这样做很方便,但如果网址多了,就会变得很麻烦……
有没有简单的方法可以直接把网址和视图对应起来呢??
谢谢。
3 个回答
1
我不太确定这种方法是否是解决这个问题的最佳方式(我在werkzeug的代码库里没有找到类似的例子,而且我还只是刚开始玩这个库),但其实你也可以简单地继承Rule这个类:
class CoolRule(Rule):
def __init__(self, view, *args, **kwargs):
self.view = view
super(CoolRule, self).__init__(*args, **kwargs)
def empty(self):
"""We need this method if we want to use
Submounts or Subdomain factories
"""
defaults = dict(self.defaults) if self.defaults else None
return CoolRule(self.view, self.rule, defaults, self.subdomain,
self.methods, self.build_only, self.endpoint,
self.strict_slashes, self.redirect_to,
self.alias, self.host)
_url_map = Map([
CoolRule(user.views.login, '/login', endpoint='user-login'),
CoolRule(user.views.logout, '/logout', endpoint='user-logout'),
])
def dispatch(request):
urls = _url_map.bind_to_environ(request.environ)
rule, arguments = urls.match(return_rule=True)
return rule.view(request, **arguments)
这样做可以保持视图命名的抽象层次,避免使用'字符串导入'这种奇怪的技巧。
3
import letters # our views module
url_map = Map([
Rule('/letters', endpoint=letters.index),
Rule('/letters/<int:item_id>', endpoint=letters.item),
Rule('/letters/<string:section_slug>', endpoint=letters.index),
Rule('/letters/<string:section_slug>/<int:item_id>',
endpoint=letters.item),
])
端点可以是任何东西,包括函数,所以你可以直接跳过Denis例子中的导入魔法。
3
这里有一个简单的例子:
import views
def app(environ, start_response):
urls = url_map.bind_to_environ(environ)
request = Request(environ)
endpoint, params = urls.match()
names = endpoint.split('.')
view = views
for name in names:
if not hasattr(view, name):
__import__(view.__name__, None, None, [name])
view = getattr(view, name)
try:
response = view(request)
except werkzeug.exceptions.HTTPException, exc:
response = exc
return response(environ, start_response)