我最近开始使用金字塔,我有一些关于它的混合应用方法的最佳实践/一般概念问题。让我试着嘲笑一个小而复杂的场景,我想做什么......
说我正在建立一个关于电影的网站,一个用户可以去添加电影的地方,像他们一样,并用它们做其他事情。这是一个理想的功能:
/
呈现templates/root.html
/movies
呈现templates/default.html
,显示电影列表/movies/123456
显示有关电影的详细信息/movies/123456/users
显示编辑此电影的用户列表/users
呈现templates/default.html
,显示用户列表/users/654321
显示有关用户的详细信息/users/654321/movies
显示此用户最喜欢的电影列表/reviews/movies
呈现templates/reviews.html
,显示 url_fetched 电影评论/admin
您可以登录并更改内容的地方/admin/movies
呈现templates/admin.html
,显示可编辑电影列表/admin/movies/123456
呈现templates/form.html
,编辑此电影额外:
movies/123/similar/234/similar/345
,其中类似的是列出相关电影的ID的电影类的属性。或者更明确的例子可能是:companies/123/partners/234/clients/345
... /movies/123456.json
有关JSON格式电影的详细信息/movies/123456.xml
有关XML格式的电影的详细信息这是我到目前为止所做的(我的观点是基于类的,为简单起见,我只列出装饰器......):
# resources.py
class Root(object):
__name__ = __parent__ = None
def __getitem__(self, name):
return None
def factory(request):
# pseudo code...
# checks for database model that's also a resource
if ModelResource:
return ModelResource()
return Root()
# main.py
def notfound(request):
return HTTPNotFound()
def wsgi_app():
config = Configurator()
config.add_translation_dirs('locale',)
config.add_renderer('.html', Jinja2Renderer)
# Static
config.add_static_view('static', 'static')
# Root
config.add_route('root', '/')
# Admin
config.add_route('admin', '/admin/*traverse', factory='factory')
config.add_route('default', '/{path}/*traverse', factory='factory')
config.add_notfound_view(notfound, append_slash=True)
config.scan('views')
return config.make_wsgi_app()
# views/root.py
@view_config(route_name='root', renderer="root.html")
def __call__():
# views/default.py
@view_defaults(route_name='default')
class DefaultView(BaseView):
@view_config(context=ModelResource, renderer="default.html")
def with_context():
@view_config()
def __call__():
# views/admin.py
@view_defaults(route_name='admin')
class AdminView(BaseView):
@view_config(context=ModelResource, renderer="admin.html")
def default(self):
@view_config(renderer="admin.html")
def __call__(self):
以下代码来自我的真实应用。 ModelResource用作视图查找的上下文,这基本上就是这篇文章的原因......由于我的所有模型(我使用Google App Engine数据存储区)都具有相同的基本功能扩展特定的超类。我的第一直觉是在这个级别添加遍历功能,这就是我创建ModelResource的原因(代码注释中的其他解释),但我开始后悔:)所以我正在寻找一些洞察力和想法如何处理这个。
class ModelResource(ndb.Model):
def __getitem__(self, name):
module = next(module for module in application.modules if module.get('class') == self.__class__.__name__)
# this can be read as: if name == 'movies' or name == 'users' or .....
if name in module.get('nodes'):
# with this setup I can set application.modules[0]['nodes'] = [u'movies', u'films', u'фильми' ]
# and use any of the defined alternatives to find a resource
# return an empty instance of the resource which can be queried in view
return self
# my models use unique numerical IDs
elif re.match(r'\d+', name):
# return instance with supplied ID
cls = self.__class__
return cls.get_by_id(name)
# this is an attempt to solve nesting issue
# if this model has repeated property it should return the class
# of the child item(s)
# for now I'm just displaying the property's value...
elif hasattr(self, name):
# TODO: ndb.KeyProperty, ndb.StructuredProperty
return getattr(self, name)
# this is an option to find resource by slug instead of ID...
elif re.match(r'\w+', name):
cls = self.__class__
instance = cls.query(cls.slug == name).get()
if instance:
return instance
raise KeyError
我基本上有两个大问题(一些子问题):
在描述的场景中我应该如何处理遍历?
__getitem__
方法)?资源应该是模型实例吗?__getitem__
的最佳做法是什么?在此方案中/movies/
__public__
和__name__
工作,可能是因为这是错误的遍历方式:)我猜测一旦找到正确的方法,嵌套资源不应成为问题。如何切换回从遍历到网址分发?
config.add_route('json', '/{path:.*}.json')
并且它使用了适当的视图,但现在这条路线永远不会匹配...... @view_config(request_method='GET')
的视图,但它在此配置中从未匹配。对于长篇文章感到抱歉,但这是相当复杂的情况。我应该提一下,真正的应用程序有10-15个模型atm,所以我正在寻找可以在一个地方处理所有事情的解决方案 - 我想避免手动设置资源树......