.. This file is a part of the AnyBlok / Pyramid project .. .. Copyright (C) 2015 Jean-Sebastien SUZANNE .. .. This Source Code Form is subject to the terms of the Mozilla Public License, .. v. 2.0. If a copy of the MPL was not distributed with this file,You can .. obtain one at http://mozilla.org/MPL/2.0/. MEMENTO ======= Anyblok / Pyramid mainly depends on: * Python 3.3+ * `AnyBlok `_ * `Pyramid `_ Add route, view, ... in pyramid config -------------------------------------- By includeme ~~~~~~~~~~~~ 1. define the view in one file in the file views.py:: from pyramid.view import view_config from pyramid.response import Response @view_config(route_name='hello') def say_hello(request): return Response('Hello %(name)s !!!' % request.matchdict) 2. define the entrypoint function in the file foo.py:: def update_pyramid_config(config): config.add_route('hello', '/hello/{name}) config.scan('.views') By blok ~~~~~~~ 1. define the view in one file of the blok in the file views.py:: from pyramid.view import view_config from pyramid.response import Response @view_config(route_name='hello') def say_hello(request): return Response('Hello %(name)s !!!' % request.matchdict) 2. add the class method ``pyramid_load_config`` in the file foo.py:: from anyblok.blok import Blok class MyBlok(Blok): ... @classmethod def pyramid_load_config(cls, config): config.add_route('hello', '/hello/{name}') config.scan(cls.__module__ + '.views') Get AnyBlok registry in view ---------------------------- By default the registry load is the registry of the ``Configuration`` ``db_name`` key. Define a simple view:: from pyramid.view import view_config from pyramid.response import Response @view_config(route_name='foo') def bar(request): registry = request.anyblok.registry nb_installed_bloks = registry.System.Blok.query().filter_by( state='installed').count() return Response("Welcome in AnyBlok application, you have %d installed " "bloks" % nb_installed_bloks) Define view which are used only if one blok is installed -------------------------------------------------------- See the link `view and route predicated `_ the goal of the prédicate is to get the access of the route or the view only if the predicate condition is validated. AnyBlok / Pyramid add the predicate ``installed_blok``:: from pyramid.view import view_config from pyramid.response import Response @view_config(route_name='foo') def bar1(request): """ This is the default view """ return Response("Welcome in AnyBlok application, you have 0 installed " "bloks") @view_config(route_name='foo', installed_blok='anyblok-core') def bar2(request): """ This view id call if the anyblok is installed """ registry = request.anyblok.registry nb_installed_bloks = registry.System.Blok.query().filter_by( state='installed').count() return Response("Welcome in AnyBlok application, you have %d installed " "bloks" % nb_installed_bloks) .. note:: Installed predicated detect if the registry is load, without registry, the installated blok can no be verify. .. note:: you can use the ``current_blok`` function to not write the blok name:: from anyblok_pyramid import current_blok @view_config(route_name='foo', installed_blok=current_blok()) def bar2(request): """ This view id call if the anyblok is installed """ registry = request.anyblok.registry nb_installed_bloks = registry.System.Blok.query().filter_by( state='installed').count() return Response("Welcome in AnyBlok application, you have %d installed " "bloks" % nb_installed_bloks) Define the name of the database ------------------------------- The name of the database determine the registry use by the view. By default the name of the database come from the ``Configuration`` ``db_name`` key. But it is possible to define a callback to define the good db name. Define an AnyBlok init function ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ In the setup of the package add new entry point:: setup( ... entry_points={ ... 'anyblok.init': ['get_db_name=package.path:add_get_db_name'], ... }, ... ) In the file ``path`` of the ``package`` add the method ``add_get_db_name``:: def add_get_db_name(): from anyblok.config import Configuration def get_db_name(request): return ``My db Name`` @Configuration.add('plugins'): def update_plugins(group): group.set_defaults(get_db_name=get_db_name) Define the db name in the request path ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ This is an example to define the good db name in function of the path of the method. This example work if the path id define like this:: config.add_route('one_route', '/{dbname}/foo/bar') The definition of ``get_db_name`` is:: def add_get_db_name(): from anyblok.config import Configuration def get_db_name(request): return request.matchdict.get( dbname', Configuration.get('db_name')) @Configuration.add('plugins'): def update_plugins(group): group.set_defaults(get_db_name=get_db_name) Authentication and authorization -------------------------------- Authentication can be add directly in configuration with includeme. Links to the official documentation : * http://docs.pylonsproject.org/projects/pyramid//en/latest/tutorials/wiki2/design.html * http://docs.pylonsproject.org/projects/pyramid//en/latest/tutorials/wiki2/authorization.html * http://docs.pylonsproject.org/projects/pyramid//en/latest/tutorials/wiki2/authentication.html * http://docs.pylonsproject.org/projects/pyramid//en/latest/quick_tutorial/authorization.html * http://docs.pylonsproject.org/projects/pyramid//en/latest/quick_tutorial/authentication.html Link to an official tutorial If you want to replace default pyramid component by your own: * http://docs.pylonsproject.org/projects/pyramid//en/latest/narr/security.html#creating-your-own-authentication-policy * http://docs.pylonsproject.org/projects/pyramid//en/latest/narr/security.html#creating-your-own-authorization-policy Add a root factory:: class RootFactory(object): def __init__(self, request): self.request = request __acl__ = [ (Allow, Everyone, 'all'), ] Add the authentication callback:: def group_finder(email, request): return ("all",) Add the includeme callable:: def pyramid_security_config(config): # Authentication policy secret = Configuration.get("authn_key", "secret") authn_policy = AuthTktAuthenticationPolicy(secret=secret, callback=group_finder) config.set_authentication_policy(authn_policy) # Authorization policy authz_policy = ACLAuthorizationPolicy() config.set_authorization_policy(authz_policy) # Root factory: only added if set in config file (no default one) config.set_root_factory(RootFactory) Add the includeme in the entry point:: setup( ..., entry_points={ 'anyblok_pyramid.includeme': [ 'pyramid_security_config=path:pyramid_security_config', ... ], }, ..., ) .. note:: Since **0.9.0** ``AnyBlok / Pyramid`` add Blok Authentication and Authorization It is on solution to get the Auth(s) in yours applications, but not a requirement. JSON adapter ------------ In the case where you need to return json value you can format the data with: * Define an adapter for the python ``type``:: def datetime_adapter(obj, request): return obj.isoformat() * Add the adapter at the pyramid configuration:: def declare_json_data_adapter(config): from pyramid.renderers import JSON json_renderer = JSON() json_renderer.add_adapter(datetime, datetime_adapter) config.add_renderer('json', json_renderer) * Add the includeme:: setup( ..., entry_points={ 'anyblok_pyramid.includeme': [ 'json_adapter=path:declare_json_data_adapter', ... ], }, ..., ) .. note:: Since **0.7.2**, Some adapter have already add in the module ``anyblok_pyramid.adapter``. :: from anyblok_pyramid.adapter import datetime_adapter from pyramid.renderers import JSON json_renderer = JSON() json_renderer.add_adapter(datetime, datetime_adapter) config.add_renderer('json', json_renderer)