bag.web.pyramid.resources module

Construction kit for Pyramid resource classes.

Example usage:

from bag.web.pyramid.resources import (
    BaseRootResource, BaseResource, IntResource,
    ancestor, ancestor_model, model_property)
from pyramid.decorator import reify
from pyramid.security import (Allow, Deny, Everyone, Authenticated,
                              ALL_PERMISSIONS)
from .models import User, Address


class RootResource(BaseRootResource):
    __acl__ = [
        (Allow, "group:admin", ALL_PERMISSIONS),
        (Allow, Authenticated, ("view_dashboard", "edit_users")),
        (Deny, Everyone, ALL_PERMISSIONS),
    ]
    factories = {}  # a static registry of Resource classes


class UserResource(IntResource):  # /users/1/
    factories = {}  # a static registry of Resource classes

    @reify
    def model(self):
        return sas.query(User).get(self.__name__)

    @reify
    def __acl__(self):
        user_id = self._request.authenticated_userid
        return [(
            Allow, f"u:{user_id}", self.model.get_permissions(user_id)
        )]


class UsersResource(BaseResource):  # /users/
    contains_cls = UserResource

    @reify
    def models(self):
        return sas.query(User)

RootResource.factories["users"] = UsersResource


class AddressResource(IntResource):  # /users/1/addresses/1
    factories = {}  # a static registry of Resource classes
    model = model_property(sas, Address, user=User)


class AddressesResource(BaseResource):  # /users/1/addresses
    contains_cls = AddressResource

    @reify
    def models(self):
        return ancestor_model(self, User).addresses

UserResource.factories["addresses"] = AddressesResource
class bag.web.pyramid.resources.BaseResource[source]

Bases: bag.web.pyramid.resources.BaseRootResource

Base class for Pyramid traversal resources.

Subclasses may define a static factories dict, used to map URL elements to other resource classes or factories. This is useful for any resource whose children fork into separate trees.

Subclasses may also represent collections, such as /books/. These subclasses must define a contains_cls attribute, whose value is to be the contained resource class.

For a subclass representing a single model instance ― e. g. /books/1/ ―, you can implement a model property; then a descendant view such as /books/1/authors/ may call ancestor_model(Book), which will find the ancestor and return the model property value. Example:

@reify
def model(self):
    return sas.query(Book).get(self.__name__)
class bag.web.pyramid.resources.BaseRootResource(request)[source]

Bases: object

Base class for your Root resource.

class bag.web.pyramid.resources.IntResource[source]

Bases: bag.web.pyramid.resources.BaseResource

Base class for resources whose name must be an int, e.g. /books/1.

validate_name(name)[source]
bag.web.pyramid.resources.ancestor(resource, cls, include_self=False)[source]

Return the first ancestor of resource that is of type cls.

bag.web.pyramid.resources.ancestor_finder(resource, predicate, include_self=False)[source]

Generate ancestors that satisfy predicate.

Generator that climbs the tree yielding resources for which predicate(current_resource) returns True.

bag.web.pyramid.resources.ancestor_model(resource, cls, include_self=False)[source]

Find in ancestors a model instance of type cls.

The search is done in the model attribute of the ancestors of resource. Returns None if not found.

bag.web.pyramid.resources.find_root(resource)[source]

Find and return the root resource.

bag.web.pyramid.resources.model_property(sas, model_cls, **ancestors)[source]

Return a property that checks ancestor IDs.

If you are using SQLAlchemy, this function returns a model property that checks some ancestor ID(s) against its foreign key(s). Example usage:

class AddressResource(BaseResource):
    model = model_property(sas, Address, user=User)