2012-11-20 114 views
5

我一直在尝试金字塔,这个遍历的东西给我发疯。我基本上是在摆弄购物车的控制面板,这是我想到的基本结构。Python金字塔遍历

登录页面

localhost:6543/admin_login 

成功登录后

localhost:6543/admin/home 

要查看所有现有产品

localhost:6543/admin/product 

编辑产品X

localhost:6543/admin/product/edit/1 

所以我的文件夹结构是这样的(大写文件型号)

  • mycart
    • resources.py
    • Admin.py
    • Product.py
    • 静态
    • 模板
    • 观看次数
      • __init__.py
      • admin.py
      • root.py

我resources.py

from pyramid.security import Authenticated 
    from pyramid.security import Allow 
    from pyramid.response import Response 

    class Root(object): 
     __name__ = '' 
     __parent__ = None 

     def __init__(self, request): 
      pass 

     def __getitem__(self, key): 

      if key == 'admin_login': 
       return Admin() 

      elif key == 'admin': 
       return Admin() 

      raise KeyError 

    class Admin(object): 

     __name__ = '' 
     __parent__ = Root 
     __acl__ = [(Allow, Authenticated, 'admin')] 

     def __init__(self): 
      pass 

views/__init.py,它只是一个空白文件。 至于root.py,它只是一个httpexceptions.HTTPNOTFOUND,404码

对于views/admin.py

from pyramid.view import view_config, render_view 
    import mycart.resources 

    from pyramid.httpexceptions import HTTPNotFound, HTTPFound 
    from mycart.views.root import strip_tags 
    from pyramid_mailer import get_mailer 
    from pyramid_mailer.message import Message 

    from pyramid.security import remember , forget , authenticated_userid 

    from pyramid.events import subscriber , BeforeRender 

    from mycart.Admin import Admin 
    from mycart.Product import Product 


    @view_config(context='mycart:resources.Admin', request_method='POST', renderer='admin/login.jinja2') 
    def login_post(context, request): 

     if 'btnLogin' in request.params: 
     token = request.session.get_csrf_token() 
     login = request.params['txtLogin'] 
     password = request.params['txtPassword'] 

     admin = Admin(login, request) 

     if admin.validate_user(password): 

      record = admin.find_user_by_login(login) 

      request.session['bs_admin_id'] = str(record['_id']) 
      request.session['bs_admin_name'] = record['usr']['fname'] + ' ' + record['usr']['lname']; 
      request.session['bs_admin_type'] = record['usr']['type'] 
      headers = remember(request, login) 
      return HTTPFound('/admin/home', headers=headers) 

     message = 'Failed login' 

     return {'message': message, 'url': '/admin_login', 'page_title': 'Failed Login'} 


     @view_config(context='mycart:resources.Admin', name="home", renderer='admin/home.jinja2', permission='admin') 
     def home(context, request): 
      logged_in = authenticated_userid(request) 
      url = request.path_info 

      admin = Admin(logged_in, request) 
      rec = admin.find_user_by_objectid(request.session['bs_admin_id']) ; 

      return { 'firstname': rec['usr']['fname'] } 


    @view_config(context='mycart:resources.Admin', name="product", renderer='admin/product_listing.jinja2', permission='admin') 
      def product_list(context, request): 
      print ('yes, showing product listing requested by ', request.session['bs_admin_id']) 

登录后,我点的URL为localhost:6543 /管理/产品,我注意到,它仍然呈现的家页面,而不是产品页面。

我知道我错过了一些东西,但我似乎无法找出原因。纵观http://docs.pylonsproject.org/projects/pyramid/en/1.3-branch/narr/traversal.html,我知道我在正确的轨道上,因为可能存在任意的细分市场。

我试图修改resources.py为以下

..... 

    class Admin(object): 

     __name__ = '' 
     __parent__ = Root 
     __acl__ = [(Allow, Authenticated, 'admin')] 

     def __init__(self): 
      pass 

     def __getitem__(self, key): 

      if key == 'product': 
      print ("WOOT! Listing products") 
      ## this is the part where I don't know what should I return or set or how should I hook it up with view_config 

      if key == 'home': 
      print ("yes, I'm home!") 
      ## this is the part where I don't know what should I return or set or how should I hook it up with view_config 

      raise KeyError 

对于这个部分,我取得了一些进展,其中它肯定打印在控制台中相应的消息。然而,我没有想到应该如何将它与view_configs联系起来,以及如果需要做出任何改变,view_configs应该是什么参数。

我不知道版本是否影响任何东西,但无论如何,我正在使用python 3。3

任何帮助将不胜感激。谢谢!

这是我第一次在python中编写多年的java代码。所以可能有一些术语/概念我不熟悉金字塔/ python。


好吧,我觉得我有点想到绕过这个遍历的东西。通过http://docs.pylonsproject.org/projects/pyramid/en/1.4-branch/narr/traversal.html阅读,2件事引起了我的注意。

例如,如果路径信息序列为[ 'A', 'B', 'C']:

- Traversal starts by acquiring the root resource of the application by calling the root factory. The root factory can be configured to return whatever object is appropriate as the traversal root of your application. 

- Next, the first element ('a') is popped from the path segment sequence and is used as a key to lookup the corresponding resource in the root. This invokes the root resource’s __getitem__ method using that value ('a') as an argument. 

- If the root resource “contains” a resource with key 'a', its __getitem__ method will return it. The context temporarily becomes the “A” resource. 

因此,基于在localhost:6543 /管理/产品,为view_config设置是像下面这样:

@view_config(背景=管理员,名字= '产品',....)

所以更改后resources.py

## class Root(object): 
     .... 


    class ProductName(object): 
     def __init__(self, _key): 
      pass 

    class Products(object): 
     __name__ = '' 
     __parent__ = Root 


     def __init__(self): 
      pass 

     def __getitem__(self, key): 
      print ('products: ', key) 
      if key == 'add': 
       return ProductName(key) 

      print ('Approaching KeyError') 
      raise KeyError 


    class Admin(object): 

     __name__ = '' 
     __parent__ = Root 
     __acl__ = [(Allow, Authenticated, 'admin')] 

     def __init__(self): 
      pass 


     def __getitem__(self, key): 

      if key == 'products': 
       print ('admin: ', key) 
       return Products() 

      raise KeyError 

而在意见/ admin.py

@view_config(context=Admin, name='products', renderer='admin/products.jinja2', permission = 'admin') 
    def product_add(context, request): 
     print 'hey products_add' 
     return { 'msg': ''} 

莫名其妙或更确切地说,它不是使产品模板,但默认404

+0

alrighty,怎么样输出为view_config的子路径?这是我的主要问题。 – Gino

回答

4

你看看在doc about traversal,因为你已经没有完全正确。 This tutorial在理解遍历中也非常有用。我会尽量在你的上下文中做一个快速解释:

首先,请求的路径是分割起始段。例如/admin/product被拆分为['admin', 'product']

然后,金字塔试图确定此请求的上下文。为此,它从递归调用__getitem__(这是另一种说法是object[segment]),它是从根(遍历)的每个段中调用的。在例子中,它确实是root['admin'],它返回一个管理对象,然后做admin['product']。它在遇到KeyError时停止。

一旦我们有了一个上下文,金字塔就用这个上下文搜索一个视图,并且其视图名称是未遍历的部分。例如,如果admin['product']引发KeyError,则金字塔会查找配置为@view_config(context=Admin, name="product")的视图。


那么,你如何制作一个应用程序呢?首先,你确定你的资源树是什么。在你的情况下,它可能看起来是这样的:

    • 联系
      • ProductContainer
        • 产品

有一个用于管理上下文(/admin/home),没有名称为ProductContainer/admin/product)视图名为home视图和对产品(/admin/product/1/edit)命名为edit视图。

+0

我已经浏览过http://docs.pylonsproject.org/projects/pyramid/en/1.4-branch/narr/traversal.html,不幸的是,merickel的教程对我来说没有任何意义。但是,金字塔不会呈现产品模板。我已经编辑了我的问题,并进行了修改...也许我的resources.py的结构错误? – Gino

+0

您必须确保对于每个对象,'__getitem__'将返回遍历中的下一个对象。你没有包含Root的代码,所以问题可能在那里。 – madjar

2

虽然我不知道下面的代码是优雅还是漏洞,但现在肯定适合我。我会把它放进去,以防有人像我一样面对同样的问题。

resources.py

class ProductName(object): 
     __name__ = '' 
     __parent__ = Root 
     __acl__ = [(Allow, Authenticated, 'admin')] 

     def __init__(self, _key): 
      pass 

    class Products(object): 

     __name__ = '' 
     __parent__ = Root 
     __acl__ = [(Allow, Authenticated, 'admin')] 

     def __init__(self): 
      pass 

     def __getitem__(self, key): 
      print ('products: ' + key) 
      if key == 'add': 
       return ProductName(key) 

      print ('Approaching KeyError') 
      raise KeyError 

的意见/ admin.py

@view_config(context="**mycart:resources.ProductName**", name="",  renderer='admin/product_add.jinja2', permission = 'admin') 
     def product_add(context, request): 
     print 'hey product add' 
     return { 'msg': ''} 

    @view_config(context="**mycart:resources.Products**", name='' , renderer='admin/product.jinja2', permission = 'admin') 
    def product(context, request): 
     print 'hey products listing' 
     return { 'msg': ''} 
+0

太棒了!您可以从视图配置中删除'name =''',因为这些是默认值。尽管你的'__name__'和'__parent__'是错误的。 name必须等于导向该对象的url部分(如果您在url/admin处获得Admin对象,则该名称必须为admin),并且父级必须是直接父级(ProductName的父级为Product)。这些用于使用'resource_url'生成网址,如果他们错了,生成的网址将会出错。 – madjar

+0

哈哈哈,是的,我也在摆弄其他子路径,并意识到这个错误,并最终修复它之前试图在这里发送垃圾邮件更多的援助。但感谢您提出的错误= D – Gino

+0

@madjar在一个侧面说明中,我在考虑root_factory,并想知道当项目开始扩展时,为多个部分设置多个工厂会更容易管理/优雅。性能明智,这可能是一个更好的做法。维护明智,这可能是一个更好的做法? – Gino