Python金字塔遍历

时间:2012-11-20 14:40:34

标签: python pyramid traversal

我一直在尝试金字塔,这种遍历让我疯狂。我基本上是在为购物车制作一个控制面板,这是我想到的基本结构。

登录页面

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
    • 静态
    • 模板
    • 的观点
      • __初始化__。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'] )

登录后,我将网址指向localhost:6543 / admin / product,我注意到它仍然呈现主页,而不是产品页面。

我知道我错过了一些东西,但我似乎无法找出原因。通过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

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

这是我在多年的java之后第一次在python中编码。所以可能有一些我对pyramid / python不熟悉的术语/概念。


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

例如,如果路径信息序列是['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 / admin / products,view_config的设置如下:

@view_config(context = Admin,name ='products',....)

所以在更改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

在views / 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。

2 个答案:

答案 0 :(得分: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
        • 产品

管理员上下文(home)有一个名为/admin/home的视图,ProductContainer/admin/product没有名称的视图)和名为{{的视图1}}表示产品(edit)。

答案 1 :(得分: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': ''}