2012-11-20 112 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