金字塔混合应用程序(遍历+网址发送)

时间:2015-06-19 09:55:29

标签: pyramid

我最近开始使用金字塔,我有一些关于它的混合应用方法的最佳实践/一般概念问题。让我试着嘲笑一个小而复杂的场景,我想做什么......

场景

说我正在建立一个关于电影的网站,一个用户可以去添加电影的地方,像他们一样,并用它们做其他事情。这是一个理想的功能:

  • /呈现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格式的电影的详细信息
  • 具有资源处理授权标头的RESTFull方法(GET,PUT,DELETE ..)

方法

这是我到目前为止所做的(我的观点是基于类的,为简单起见,我只列出装饰器......):

# 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

的问题

我基本上有两个大问题(一些子问题):

  • 在描述的场景中我应该如何处理遍历?

    1. 我应该扩展某个类,还是实现接口,还是其他什么?
    2. 应该在模型级别处理遍历(电影模型,还是它的超类会有__getitem__方法)?资源应该是模型实例吗?
    3. 返回资源集合(列表)的__getitem__的最佳做法是什么?在此方案中/movies/
    4. 上面代码中的我的ModelResource不是位置感知 ...我无法让__public____name__工作,可能是因为这是错误的遍历方式:)我猜测一旦找到正确的方法,嵌套资源不应成为问题。
  • 如何切换回从遍历到网址分发?

    1. 对于额外的东西:如何设置不同的渲染器来处理JSON请求?在我添加遍历之前,我配置了config.add_route('json', '/{path:.*}.json')并且它使用了适当的视图,但现在这条路线永远不会匹配......
    2. 与上面相同的问题 - 我添加了一个处理HTTP方法@view_config(request_method='GET')的视图,但它在此配置中从未匹配。

对于长篇文章感到抱歉,但这是相当复杂的情况。我应该提一下,真正的应用程序有10-15个模型atm,所以我正在寻找可以在一个地方处理所有事情的解决方案 - 我想避免手动设置资源树......

0 个答案:

没有答案