Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pyramid traversal is doing my head in

I am trying to get my head around Pyramid traversal with this very simple example. What I haven't quite grasped yet is where to "inject" an Article object from the db.

As it is, /Article correctly finds and renders the article_view but that's fairly useless. How/when/where do I use the next part of the URL to query for a particular Article from the db? eg. /Article/5048230b2485d614ecec341d.

Any clues would be great!

init.py

from pyramid.config import Configurator
from pyramid.events import subscriber
from pyramid.events import NewRequest
import pymongo

from otk.resources import Root

def main(global_config, **settings):
    """ This function returns a WSGI application.
    """
    config = Configurator(settings=settings, root_factory=Root)
    config.add_static_view('static', 'otk:static')
    # MongoDB
    def add_mongo_db(event):
        settings = event.request.registry.settings
        url = settings['mongodb.url']
        db_name = settings['mongodb.db_name']
        db = settings['mongodb_conn'][db_name]
        event.request.db = db
    db_uri = settings['mongodb.url']
    MongoDB = pymongo.Connection
    if 'pyramid_debugtoolbar' in set(settings.values()):
        class MongoDB(pymongo.Connection):
            def __html__(self):
                return 'MongoDB: <b>{}></b>'.format(self)
    conn = MongoDB(db_uri)
    config.registry.settings['mongodb_conn'] = conn
    config.add_subscriber(add_mongo_db, NewRequest)
    config.include('pyramid_jinja2')
    config.include('pyramid_debugtoolbar')
    config.scan('otk')
    return config.make_wsgi_app()

resources.py

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

    def __init__(self, request):
        self.request = request

    def __getitem__(self, key):
        if key == 'Article':
            return Article(self.request)
        else:
            raise KeyError

class Article:
    __name__ = ''
    __parent__ = Root

    def __init__(self, request):
        self.reqeust = request

    # so I guess in here I need to update the Article with
    # with the document I get from the db.  How?

    def __getitem__(self, key):
        raise KeyError

views.py

from pyramid.view import view_config
from otk.resources import *
from pyramid.response import Response

@view_config(context=Root, renderer='templates/index.jinja2')
def index(request):
    return {'project':'OTK'}

@view_config(context=Article, renderer='templates/view/article.jinja2')
def article_view(context, request):
    # I end up with an instance of Article here as the context.. but 
    # at the moment, the Article is empty
    return {}
like image 276
MFB Avatar asked Sep 06 '12 08:09

MFB


1 Answers

You'd generally return a Article object from the id part of the URL traversal.

What happens with traversal is that for each element in the URL path, an object is looked up and made the new current object for the next path element lookup.

So for Article, the root object is asked for something matching that name, and the result of that lookup is made the new "current" object, and 5048230b2485d614ecec341d is then looked up on that new object.

So, what you are looking for is a dispatcher object, something that looks up articles based on the longer id you are passed, and that returns your Article instances:

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

    def __init__(self, request):
        self.request = request

    def __getitem__(self, key):
        if key == 'articles':
            dispatch =  ArticleDispatcher(self.request)
            dispatch.__name__ = key
            dispatch.__parent__ = self
            return dispatch
        raise KeyError(key)

class ArticleDispatcher(object):
    __name__ = None
    __parent__ = None

    def __init__(self, request):
        self.request = request

    def __getitem__(self, key):
        # Get a hold of the database here:
        db = findDatabase(self.request)
        if db.exists(key):          
            data = db.load(key)
            art = Article(data)
            art.__name__ = key
            art.__parent__ = self
            return art
        raise KeyError(key)

class Article:
    __name__ = None
    __parent__ = None

    def __init__(self, data):
        self.data = data

Note how I returned a ArticleDispatcher when you use the /articles URL path, and also how I set the __name__ and __parent__ variables; you'll need those to be able to generate URLs for those instances.

The Article object returned now contains the actual article data, and the view can access that information when rendering.

You really want to go and study the Pyramid Traversal tutorial which explains this all in more detail.

like image 122
Martijn Pieters Avatar answered Nov 14 '22 23:11

Martijn Pieters