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 {}
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With