pyramid: mixing traversal and pylons controllers ?

77 views
Skip to first unread message

pipoun

unread,
Feb 16, 2012, 10:57:31 AM2/16/12
to pylons-...@googlegroups.com
Hello,

I am trying to find a way to mix a bit of the traversal resource building and the pylons controllers functions that have mapped parameters. I am also using sqlachemy as orm (so no ZODB).

Basically, I'm looking for a way to avoid as much as possible the manual extraction of parameters from the request object (especially request.matchdict).

From the sqla wiki tutorial I have:
def edit_page(request):
    name = request.matchdict['pagename']
    page = DBSession.query(Page).filter_by(name=name).one()
    ...
    body = request.params['body']

I would like to use a view class and modify the latter function to have sort of:

@view_config(...)  # necessary to add context mapping?
class PageView(object):
    def __init__( self, request, ... ):
        self.request = request
        self.context = ...
        self.page = ...  # instance of Page, but self.page is self.context ?

    ....  # index method

    # the association between url http://../page/**/edit to edit_post is missing
    @view_config(request_method='POST', renderer='template/edit.html')
    def edit_post(self, body):
        self.page.body = body
        return {'page': self.page}

    # the association between url http://../page/**/delete should be automatic
    @view_config()
    def delete( self ):
        DBSession.delete(self.page)
        ...  # redirect to another page...

   
So the url will be: http://.../page/42/edit. And the other views for instance, http://.../page/42/delete, http://.../page/42/merge_with_page/76, http://.../page/42/do_some_stuff and so on...
   
Well that's it for the handler/controller code, but all the code relative to:
- the creation of the context
- the view mapping (url chunks to function params)
- the configuration of the association between url and the views
are missing, and that's why I'm here :)

I've read the two wiki tutorials, looked at pyramid_handlers, akhet, pyramid_metatg, the View Mapper hook, and saw also the "View Callables as a Class and Dependency Injection" on the list. I have perhaps to many separate information, like pyr_handlers/pyr_metatg don't work with traversal; traversal "should be" used with zodb, url dispatch "should be" used with sqla; the view mapper example uses add_handler and url dispatch, so no traversal possible. I understand the traversal mechanism, but I'm not comfortable with the resource/context creation (the tutorial uses ZODB, I'm using sqla)...

I also have to handle the add_page typed views, where the page has not been created in the DB.
I'm obviously seeing that for each call to the view functions, an instance of Page is going to be created which will be perhaps not always necessary...
And cherry on the cake, with automatic routing as the delete view example.

So, am I missing something? Is is too complicated? Or not following the pyramid philosophy? Do I really have to use traversal?
( I come from a turbogears2 background, so my mind may be a bit unconsciously biased. )

Thanks a lot, cheers.

pipoun

Mike Orr

unread,
Feb 17, 2012, 11:12:55 PM2/17/12
to pylons-...@googlegroups.com
On Thu, Feb 16, 2012 at 7:57 AM, pipoun <pip...@gmail.com> wrote:
> I am trying to find a way to mix a bit of the traversal resource building
> and the pylons controllers functions that have mapped parameters. I am also
> using sqlachemy as orm (so no ZODB).

> Basically, I'm looking for a way to avoid as much as possible the manual
> extraction of parameters from the request object (especially
> request.matchdict).

> I've read the two wiki tutorials, looked at pyramid_handlers, akhet,


> pyramid_metatg, the View Mapper hook, and saw also the "View Callables as a
> Class and Dependency Injection" on the list. I have perhaps to many separate
> information, like pyr_handlers/pyr_metatg don't work with traversal;
> traversal "should be" used with zodb, url dispatch "should be" used with
> sqla; the view mapper example uses add_handler and url dispatch, so no
> traversal possible. I understand the traversal mechanism, but I'm not
> comfortable with the resource/context creation (the tutorial uses ZODB, I'm
> using sqla)...

> So, am I missing something? Is is too complicated? Or not following the
> pyramid philosophy? Do I really have to use traversal?
> ( I come from a turbogears2 background, so my mind may be a bit
> unconsciously biased. )

I'm having trouble understanding your question. Are you saying that
you'd rather use traversal completely, and not use URL dipatch? Do you
want an example of using traversal with SQLAlchemy? When you say
"avoid the manual extraction of parameters", do you mean that you
don't want to use URL dispatch, or that you just don't like
request.matchdict for some reason?

You can use traversal with SQLAlchmey. The Kotti project is the best
example of it, and you can study the source but it's complex. I don't
know of a SQLAlchemy-wiki-traversal tutorial, perhaps somebody should
write one. There are two ways to approach traversal with SQLAlchemy.

If you're doing a single level without recursion; e.g., "/page/ABC",
your root would have a "page" key, which would be some object that
queries the Page table and fetches an "ABC" record. That record either
becomes the resource, or you have some kind of resource class and put
the record inside it.

If you're doing multi-level recursion ("/page/A/B/C" or perhaps
"/A/B/C"), you would need a self-referential table; i.e., a table with
a foreign key column pointing to the same table. Then each record can
point to its parent. Kotti is an example of this.

Traversal is most commonly used with an object database because both
of them are naturally recursive. But I'm seeing more and more use of
traversal with SQLAlchemy, so perhaps it will become just as common in
the future?

--
Mike Orr <slugg...@gmail.com>

pipoun

unread,
Feb 20, 2012, 9:57:58 AM2/20/12
to pylons-...@googlegroups.com

On Saturday, February 18, 2012 5:12:55 AM UTC+1, Mike Orr wrote:
On Thu, Feb 16, 2012 at 7:57 AM, pipoun wrote:
> I am trying to find a way to mix a bit of the traversal resource building
> and the pylons controllers functions that have mapped parameters. I am also
> using sqlachemy as orm (so no ZODB).

> Basically, I'm looking for a way to avoid as much as possible the manual
> extraction of parameters from the request object (especially
> request.matchdict).

I'm having trouble understanding your question. Are you saying that

you'd rather use traversal completely, and not use URL dipatch? Do you
want an example of using traversal with SQLAlchemy? When you say
"avoid the manual extraction of parameters", do you mean that you
don't want to use URL dispatch, or that you just don't like
request.matchdict for some reason?

 
Sorry for my lack of clarity, the different possibilities and guidelines didn't help me to get my mind cleaned up.
The main goal is 1/ to avoid the manual instantiation of orm objects, and 2/ mapping the rest of the URL to function parameters (i.e. pylons controller). And I was just wondering if traversal was a better fit for achieving this, because it seemed more natural.
So as a fact if I use URL dispatch, it will be playing with request.matchdict.
I think 1/ is actually quite close to your post "Limited traversal" (which gave me an example of how to do it).

You can use traversal with SQLAlchmey. The Kotti project is the best
example of it, and you can study the source but it's complex. I don't
know of a SQLAlchemy-wiki-traversal tutorial, perhaps somebody should
write one. There are two ways to approach traversal with SQLAlchemy.

If you're doing a single level without recursion; e.g., "/page/ABC",
your root would have a "page" key, which would be some object that
queries the Page table and fetches an "ABC" record. That record either
becomes the resource, or you have some kind of resource class and put
the record inside it.


Yeah I was thinking about one level of recursion, not a generic tree, but more like a rake.

Anyway, I went to #pyramid to lurk/ask/whine and mcdonc helped a lot.
I've figured out that for a classic traversal with sqla system, I have to design table with a self referencing foreign key.
Then I was strongly recommended not to mix traversal & url dispatch.
And finally, he showed me that I could do everything with a view mapper.
I've modified a chunk of code from the "Using Hooks" page
{{{
class PylonsControllerViewMapper(object):
    def __init__(self, **kw):
        self.kw = kw

    def __call__(self, view):
        attr = self.kw['attr']
        def wrapper(context, request):
            matchdict = request.matchdict.copy()
            matchdict.pop('action', None)
            view_inst = view()
            if view.orm_type is not None:
                orm_id = matchdict.pop('id', None)
                if orm_id is not None:
                    view_inst.orm_inst = DBSession.query(
                        view.orm_type).filter_by(id=orm_id).one()
            meth = getattr(view_inst, attr)
            if matchdict:
                return meth(**matchdict)
            else:
                return meth()
        return wrapper

class BaseController(object):
    __view_mapper__ = PylonsControllerViewMapper
    orm_type = None
   
class PageController(BaseController):
    orm_type = models.Page
}}}

The route will be of course following this pattern: '/page/{id}/{action}'. (This is not the best example as all the subparts of the url are going to be chomped by the view mapper)
 

If you're doing multi-level recursion ("/page/A/B/C" or perhaps
"/A/B/C"), you would need a self-referential table; i.e., a table with
a foreign key column pointing to the same table. Then each record can
point to its parent. Kotti is an example of this.

Traversal is most commonly used with an object database because both
of them are naturally recursive. But I'm seeing more and more use of
traversal with SQLAlchemy, so perhaps it will become just as common in
the future?


By the way, when looking at the Akhet documentation (latest), the pylons guide has been moved to the pyramid cookbook, which is not online yet. Where can I get it otherwise? Do you know if it will be online soon?

Thanks a lot!
pipoun
 

--
Mike Orr

Mike Orr

unread,
Feb 20, 2012, 3:31:07 PM2/20/12
to pylons-...@googlegroups.com
On Mon, Feb 20, 2012 at 6:57 AM, pipoun <pip...@gmail.com> wrote:
> I think 1/ is actually quite close to your post "Limited traversal" (which
> gave me an example of how to do it).

I'm leaning toward going back to URL dispatch for the use case I
showed, because of the issues re generating a URL and needing a
generation route anyway.

It sounds like we need a tutorial on traversal with SQLAlchemy, one
for non-recursive and one for recursive. The wiki tutorial may be
suitable for non-recursive, and a stripped-down version of Kotti for
recursive.

> And finally, he showed me that I could do everything with a view mapper.

What is a view mapper and what does it do? According to the glossary,
it prepares the view's arguments and modifies its return value? It
says it's mainly used by extension builders so I haven't looked
further into it. (Look! Here's something for that super-advanced
manual we've been talking about. :)

> By the way, when looking at the Akhet documentation (latest), the pylons
> guide has been moved to the pyramid cookbook, which is not online yet. Where
> can I get it otherwise? Do you know if it will be online soon?

I'm working on it today, actually. I just finished organizing the
cookbook into topic-sections, so I can distribute the material to
their appropriate sections.

--
Mike Orr <slugg...@gmail.com>

pipoun

unread,
Feb 21, 2012, 4:43:26 AM2/21/12
to pylons-...@googlegroups.com

On Monday, February 20, 2012 9:31:07 PM UTC+1, Mike Orr wrote:
On Mon, Feb 20, 2012 at 6:57 AM, pipoun wrote:

> And finally, he showed me that I could do everything with a view mapper.

What is a view mapper and what does it do? According to the glossary,
it prepares the view's arguments and modifies its return value? It
says it's mainly used by extension builders so I haven't looked
further into it.  (Look! Here's something for that super-advanced
manual we've been talking about. :)


I don't think you're going to learn something, but I took the code snippet from: http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/hooks.html#using-a-view-mapper
imo, it's just a decorator for the methods of the view class. you just have to find out which view method to use (with the 'attr' keyword)
It would be nice if I had more information regarding the keyword arguments of the constructor. I also should look into the code of the default view mapper provided by pyramid.

> By the way, when looking at the Akhet documentation (latest), the pylons
> guide has been moved to the pyramid cookbook, which is not online yet. Where
> can I get it otherwise? Do you know if it will be online soon?

I'm working on it today, actually. I just finished organizing the
cookbook into topic-sections, so I can distribute the material to
their appropriate sections.


Great, thank you so much.

pipoun
 

--
Mike Orr

Reply all
Reply to author
Forward
0 new messages