2012-11-20 20 views
5

Próbowałem piramidy, a ta traversal przesyła mi orzechy. Zasadniczo robię wszystko, żeby stworzyć panel kontrolny dla koszyka na zakupy i to jest podstawowa struktura, którą mam na myśli.Przenoszenie piramidy w Pythonie

strona logowania

localhost:6543/admin_login 

Po udanym logowaniu

localhost:6543/admin/home 

Aby wyświetlić wszystkie istniejące produkty

localhost:6543/admin/product 

Aby edytować produktów X

localhost:6543/admin/product/edit/1 

Więc moja struktura folderów jest coś takiego (Zainwestuj pliki są modele)

  • mycart
    • resources.py
    • Admin.py
    • Product.py
    • statyczne
    • szablony
    • wyświetleń
      • __init__.py
      • admin.py
      • root.py

Moja 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 

W views/__init.py, to po prostu pusty plik. chodzi o root.py, to po prostu kod httpexceptions.HTTPNOTFOUND, 404

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

Po zalogowaniu, wskazuję url na localhost: 6543/admin/produkt, zauważam, że nadal renderowania domu stronę, zamiast strony produktu.

Wiem, że coś mi umknęło, ale nie mogę się dowiedzieć dlaczego. Patrząc przez http://docs.pylonsproject.org/projects/pyramid/en/1.3-branch/narr/traversal.html, wiem, że jestem na dobrej drodze, ponieważ mogą istnieć arbitralne segmenty.

Próbowałem modyfikowania resources.py być następujące

..... 

    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 

dla tej części, zrobiłem pewne postępy, gdzie jest zdecydowanie drukując odpowiedni komunikat w konsoli. Jednak nie mam pojęcia, jak powinienem podłączyć go do view_configs i jakie powinny być parametry dla view_configs, jeśli trzeba wprowadzić jakieś zmiany.

Nie wiem, czy wersja wpływa na wszystko, ale tak czy inaczej, używam Pythona 3.3

Każda pomoc zostanie doceniona. Dzięki!

To jest mój pierwszy kodowanie w języku Python po latach java. Być może istnieją pewne terminy/koncepcje, których nie znam w odniesieniu do piramidy/Pythona.


OK, wydaje mi się, że mam ochotę otoczyć ten temat. Czytając przez http://docs.pylonsproject.org/projects/pyramid/en/1.4-branch/narr/traversal.html, 2 rzeczy przykuło moją uwagę.

Na przykład, jeżeli sekwencja informacji ścieżka [ '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. 

więc oparty na localhost: 6543/admin/produkty, ustawienia view_config jest jak następuje:

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

więc po wprowadzeniu zmian do 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 

aw odsłon/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': ''} 

Tak czy raczej to nie jest świadczenie szablon produktu, ale domyślne 404.

+0

W porządku, a co z wyjściem na view_config dla podścieżek? To główny problem, który mam. – Gino

Odpowiedz

4

spojrzeć na doc about traversal, bo masz nie mam tego całkiem w porządku. This tutorial jest również bardzo przydatny w zrozumieniu przejścia. Spróbuję zrobić szybkie wyjaśnienie w twoim kontekście:

Przede wszystkim ścieżka żądania jest podzielona na segmenty wstępne. Na przykład /admin/product jest podzielony na ['admin', 'product'].

Następnie piramida próbuje określić kontekst dla tego żądania. W tym celu rekursywnie wywołuje __getitem__ (co jest po prostu innym sposobem, aby powiedzieć, że robi object[segment]) dla każdego segmentu z katalogu głównego (przechodzi przez niego). Na przykład, robi to root['admin'], która zwraca obiekt admin, następnie robi admin['product']. Zatrzymuje się, gdy napotka błąd KeyError.

Kiedy już mamy kontekst, piramida wyszukuje widok z tym kontekstem i którego nazwa widoku jest częścią, która nie została przemierzona. Na przykład, jeśli admin['product'] podniesie KeyError, piramida szuka widoku skonfigurowanego z @view_config(context=Admin, name="product").


Więc jak zrobić aplikację z tego? Najpierw ustalasz, jakie jest twoje drzewo zasobów.W twoim przypadku, to może wyglądać następująco:

  • głównej
    • Admin
      • ProductContainer
        • wyrobów

Istnieje pogląd, nazwany home w kontekście administracyjnym (/admin/home), widok bez nazwy dla ProductContainer (/admin/product) i widok nazwany edit dla produktu (/admin/product/1/edit).

+0

Przeszedłem http://docs.pylonsproject.org/projects/pyramid/en/1.4-branch/narr/traversal.html, niestety samouczek merickela nie ma dla mnie sensu. Jednak w jakiś sposób piramida nie renderuje szablonu produktu. Zmieniłem moje pytanie z wprowadzonymi modyfikacjami ... Być może mój resources.py jest źle skonstruowany? – Gino

+0

Musisz się upewnić, że dla każdego obiektu '__getitem__' zwróci następny obiekt podczas przejścia. Nie uwzględniłeś kodu Root, więc być może problem jest. – madjar

2

Podczas gdy nie wiem, czy poniższy kod jest elegancki lub luki, to zdecydowanie działa dla mnie teraz. Włożę to, na wypadek, gdyby ktoś zmierzył się z tym samym problemem, co ja.

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 

odsłon/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

Świetnie! Prawdopodobnie możesz usunąć 'name = ''' z konfiguracji widoku, ponieważ są to wartości domyślne. Twoje '__name__' i' __parent__' są jednak błędne. nazwa musi być równa sekcji adresu URL, która prowadzi do tego obiektu (jeśli otrzymasz obiekt Admin pod adresem url/admin, to nazwa musi być nazwą administratora), a rodzic musi być bezpośrednim rodzicem (rodzicem ProductName jest Product). Są one używane do generowania adresów URL za pomocą 'resource_url', jeśli są one błędne, wygenerowany adres URL będzie niepoprawny. – madjar

+0

Hahaha, tak, ja też bawię się z innymi ścieżkami podrzędnymi, i zdałem sobie sprawę z tego błędu i ostatecznie naprawiłem go przed próbami spamowania tutaj w celu uzyskania większej pomocy. Ale dziękuję, że główki wskazywały błąd = D – Gino

+0

@madjar Na marginesie, myślałem o root_factory i zastanawiałem się, czy będzie łatwiejsze do zarządzania/eleganckie posiadanie wielu fabryk dla różnych części, gdy projekt zacznie się powiększać. Wydajność, która może być lepszą praktyką. Konserwacja mądra, która może być lepszą praktyką? – Gino