2012-11-20 17 views
5

Sto provando piramide e questa cosa trasversale mi sta mandando fuori di testa. Sto praticamente cercando di creare un pannello di controllo per un carrello della spesa e questa è la struttura di base che ho in mente.Python Pyramid traversal

La pagina di login

localhost:6543/admin_login 

Su login riuscito

localhost:6543/admin/home 

Per vedere tutti i prodotti esistenti

localhost:6543/admin/product 

Per modificare il prodotto X

localhost:6543/admin/product/edit/1 

Così la mia struttura di cartelle è qualcosa di simile (Capitalizzare file sono modelli)

  • mycart
    • resources.py
    • Admin.py
    • Product.py
    • statici
    • modelli
    • visualizzazioni
      • __init__.py
      • admin.py
      • root.py

mio 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 

In views/__init.py, è semplicemente un file vuoto. Per quanto riguarda root.py, è semplicemente un codice httpexceptions.HTTPNOTFOUND, 404

Per 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']) 

Dopo il login, io punto l'url a localhost: 6543/admin/prodotto, mi accorgo che ancora il rendering della casa pagina, invece della pagina del prodotto.

So che ho perso qualcosa ma non riesco a capire perché. Guardando attraverso http://docs.pylonsproject.org/projects/pyramid/en/1.3-branch/narr/traversal.html, so che sono sulla strada giusta in quanto potrebbero esserci segmenti arbitari.

Ho cercato di modificare resources.py essere la seguente

..... 

    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 

Per questa parte, ho fatto qualche progresso in cui è sicuramente la stampa del relativo messaggio nella console. Tuttavia, non ho idea di come dovrei collegarlo con view_configs e quali dovrebbero essere i parametri per view_configs se è necessario apportare delle modifiche.

Non so se la versione influisce su qualcosa, ma in ogni caso, sto usando python 3.3

Qualsiasi aiuto sarà apprezzato. Grazie!

Questa è la mia prima volta in Python dopo anni di java. Quindi potrebbero esserci alcuni termini/concetti che non mi sono familiari rispetto a pyramid/python.


Ok, penso che mi sia fatto in modo di avvolgere questa cosa trasversale. Leggendo il numero http://docs.pylonsproject.org/projects/pyramid/en/1.4-branch/narr/traversal.html, 2 cose hanno attirato la mia attenzione.

Ad esempio, se la sequenza informazioni percorso è [ '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. 

Quindi, sulla base localhost: 6543/admin/prodotti, le impostazioni per view_config è come la seguente:

@view_config (context = Admin, nome = 'prodotti', ....)

Così, dopo aver apportato modifiche al 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 

E in vista/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': ''} 

In qualche modo, o meglio, non sta rendendo il modello di prodotto, ma il valore predefinito 404.

+0

Alrighty, per quanto riguarda l'uscita per il view_config per sottotracciati? Questo è il problema principale che sto avendo. – Gino

risposta

4

si dà un'occhiata al doc about traversal, perché hai non ho capito bene This tutorial è anche abbastanza utile per comprendere l'attraversamento. Proverò a fare una rapida spiegazione nel tuo contesto:

Prima di tutto, il percorso della richiesta è diviso in segmenti di introduzione. Ad esempio, /admin/product viene diviso in ['admin', 'product'].

Quindi, la piramide tenta di determinare il contesto per questa richiesta. Per questo, chiama ricorsivamente __getitem__ (che è solo un altro modo per dire che fa object[segment]) per ogni segmento dalla radice (attraversa). Nell'esempio, fa root['admin'], che restituisce un oggetto admin, quindi fa admin['product']. Si ferma quando incontra un KeyError.

Una volta che abbiamo un contesto, piramide cerca una vista con questo contesto e il cui nome di vista è la parte che non è stata attraversata. Ad esempio, se admin['product'] genera un KeyError, Pyramid cerca una vista configurata con @view_config(context=Admin, name="product").


Quindi, come si crea un'app da questo? In primo luogo, si determina qual è il tuo albero delle risorse.Nel tuo caso, potrebbe assomiglia a questo:

  • Root
    • Admin
      • ProductContainer
        • prodotto

C'è una vista con nome home per il contesto Admin (/admin/home), una vista senza nome per il ProductContainer (/admin/product) e una vista con nome edit per il prodotto (/admin/product/1/edit).

+0

Ho esaminato http://docs.pylonsproject.org/projects/pyramid/en/1.4-branch/narr/traversal.html, sfortunatamente, il tutorial di merickel non ha senso per me. Tuttavia, in qualche modo piramide non sta rendendo il modello del prodotto. Ho modificato la mia domanda con le modifiche apportate ... Forse my resources.py è strutturato in modo errato? – Gino

+0

Devi assicurarti che, per ogni oggetto, '__getitem__' restituirà l'oggetto successivo nella traversata. Non hai incluso il codice per Root, quindi forse il problema è lì. – madjar

2

Mentre non so se il codice di seguito è elegante o qualsiasi scappatoia, è sicuramente funzionante per me ora. Lo inserirò, nel caso qualcuno affronta lo stesso problema come me.

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 

viste/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

Ottimo! Probabilmente puoi rimuovere 'name = ''' dalla vista config, dato che questi sono i valori predefiniti. Il tuo '__name__' e' __parent__' sono però sbagliati. il nome deve essere uguale alla sezione url che porta a quell'oggetto (se si ottiene un oggetto Admin su url/admin, il nome deve essere admin), e il genitore deve essere il genitore diretto (il genitore di ProductName è Product). Questi sono usati per generare url usando 'resource_url', se sono sbagliati l'URL generato sarà sbagliato. – madjar

+0

Hahaha, sì, sto armeggiando anche con altri sotto-percorsi, e mi sono reso conto di questo errore e alla fine lo ho risolto prima di tentare di inviare spam qui per ulteriori aiuti. Ma grazie per aver fatto notare l'errore = D – Gino

+0

@madjar In una nota a margine, stavo pensando a root_factory e mi chiedevo sarebbe più maneggevole/elegante avere più factory per le varie parti quando il progetto inizia ad aumentare. Prestazioni saggio, che potrebbe essere una pratica migliore. Saggio di manutenzione, che potrebbe essere una pratica migliore? – Gino

Problemi correlati