Einar Johnson
Einar Johnson

Reputation: 3

Building a REST API in Pyramid using traversal

I am trying to build a simple REST API using the Python pyramid framework. I am having troubles getting a view callable executed when I have nested classes. (webkey class inside the auth class)

I define my resources like this

from __future__ import absolute_import
from pyramid.traversal import find_root

import logging
log = logging.getLogger(__name__)


class Resource(dict):
    def __init__(self, ref, parent):
        self.__name__ = ref
        self.__parent__ = parent

    def __repr__(self):
        # use standard object representation (not dict's)
        return object.__repr__(self)

    def add_child(self, ref, klass):
        resource = klass(ref=ref, parent=self)
        self[ref] = resource

class Root(Resource):
    def __init__(self, request):
        Resource.__init__(self, ref='', parent=None)
        self.request = request
        self.add_child('auth', auth)
        self['auth'].add_child('webkey', webkey)

class auth(Resource):
    def __init__(self, ref, parent):
        self.__name__ = ref
        self.__parent__ = parent            

    def collection(self):
        root = find_root(self)
        request = root.request
        return request.db[self.collection_name]

    def retrieve(self):
        return [elem for elem in self.collection.find()]

    def create(self, document):
        object_id = self.collection.insert(document)

        return self.resource_name(ref=str(object_id), parent=self)

    def __getitem__(self, ref):
        return auth(ref, self)

    def getDesc(self):
        return 'Base authentication class'

class webkey(Resource):

    def __init__(self, ref, parent):
        self.__name__ = ref
        self.__parent__ = parent

    def collection(self):
        root = find_root(self)
        request = root.request
        return request.db[self.collection_name]

    def retrieve(self):
        return [elem for elem in self.collection.find()]

    def create(self, document):
        object_id = self.collection.insert(document)

        return self.resource_name(ref=str(object_id), parent=self)

    def __getitem__(self, ref):
        return webkey(ref, self)

    def getDesc(self):
        return 'Web key authentication class'

And my views as

from pyramid.view import view_config

from patientapi.resources.resources import Root, auth, webkey

import logging
log = logging.getLogger(__name__)

@view_config(renderer='json', context=Root)
def home(context, request):
    return {'info': 'DigiDoc API'}

@view_config(renderer='json', context=auth)
def getbasic(context, request):
    return {'AuthModule': context.getDesc()}

@view_config(renderer='json', context=webkey)
def getweb(context, request):
    return {'WEBAuthModule': context.getDesc()}

The initialization is very basic also

def main(global_config, **settings):
    """ This function returns a Pyramid WSGI application.
    """
    config = Configurator(settings=settings, root_factory=Root)

    config.scan('.views')
    return config.make_wsgi_app()

When I get the webkey URI using: curl localhost:6543/auth/webkey the getBasic view callable is executed. I am trying to figure out why the getWeb view callable is not executed. Am I nesting the classes in a wrong way in the resources script? When I view the dictionary structure in pshell it looks like this:

    print(root.keys())
    dict_keys(['auth'])
    print(root['auth'].keys())
    dict_keys(['webkey'])
    print(root['auth']['webkey'].keys())
    dict_keys([])

Upvotes: 0

Views: 493

Answers (1)

enkidulan
enkidulan

Reputation: 42

On a lookup operation class auth every time returns a new instance of itself and this is the reason why getweb view is never called.

class auth(Resource):
    ...
    def __getitem__(self, ref):
        # it always returns a new instance of auth class, 
        # and that is why context will always by `auth`
        return auth(ref, self)
    ...

Also creating new instances of a class on lookup operation doesn't feel right. Pyramid's traversal tutorial has very nice and simple examples of how to build a traversal application. For complex examples I would recommend to check Kotti source code.

Upvotes: 1

Related Questions