September 06, 2010

shabti_formalchemy – “Pylons Admin” Web UI

Note

This Shabti template was kindly contributed by Gaël Pasgrimaud of the Formalchemy development team.

This template is a basic shabti auth setup which has been configured to use the Formalchemy package. Formalchemy generates HTML form fields and tables from SQLAlchemy mapped classes or manually added Fields. And, also, Elixir mapped classes. In this template, the standard Shabti identity model is coupled with FormAlchemy’s “Pylons Admin” facility to produce an auto-generated facility for administrating the population of the identity model.

In essence this template provides an out-of-the-box web interface for maintaining a lightweight identity model of Users, Groups and Permissions. Using the Pylons Admin interface is straightforward, direct and the interface itself is quite self-explanatory.

Note

shabti_formalchemy source code is in the bitbucket code repository

About Formalchemy

The following description is taken from the Formalchemy project web site ...

“FormAlchemy greatly speeds development with SQLAlchemy mapped classes (models) in a HTML forms environment.

FormAlchemy eliminates boilerplate by autogenerating HTML input fields from a given model. FormAlchemy will try to figure out what kind of HTML code should be returned by introspecting the model’s properties and generate ready-to-use HTML code that will fit the developer’s application.

Of course, FormAlchemy can’t figure out everything, i.e, the developer might want to display only a few columns from the given model. Thus, FormAlchemy is also highly customizable.”

See also

For further details, see the project documentation

Dependencies

You need to easy-install FormAlchemy and easy-install fa.jquery before using the template.

Using the template

After successfully installing Shabti, additional paster templates will be available. Simply create a Shabti-configured project by specifying that paster should use the shabti_formalchemy template:

$ paster create -t shabti_formalchemy myproj

These are the option dialogue choices appropriate for the Shabti auth shabti_formalchemy template — which uses mako templates and requires SQLAlchemy ...

(mako/genshi/jinja/etc: Template language) ['mako']:
(True/False: Include SQLAlchemy 0.4 configuration) [False]: True

Once the project has been created, navigate to the project directory.

The next step is to initialise the database by running the project setup script which will create the initial entries.

$ paster setup-app development.ini

The next (optional) step after initialising the relational store is to run the tests.

$ nosetests

8/10 tests should run successfully. Two are known to fail but these failures appear to be restricted to the test environment, normal functioning remains unaffected.

Running the generated app

After initialising and testing, start the Pylons web app with:

$ paster serve --reload development.ini

The Shabti Formalchemy template’s variant on the standard Pylons welcome screen is browsable at at http://localhost:5000/ ...

Welcome screen

../_images/shabti_formalchemy_welcome.jpg

Note

The identity admin interface is pre-rolled and is accessible via the “Admin WUI” link.

Template details

This template is an extension of the standard shabti auth template that adds and routes an “admin” controller for the CRUD operations on the identity model and an ancillary “jquery” controller whose sole purpose is the handling of the resolution of JQuery libs.

The “admin” controller imports the standard Shabti Elixir-mapped identity model of User, Permission and Group entities and hooks them up to FormAlchemy:

import logging
from MYPROJ.lib.base import BaseController, render
from MYPROJ import model
from MYPROJ import forms
from formalchemy.ext.pylons.admin import FormAlchemyAdminController

log = logging.getLogger(__name__)

class AdminController(BaseController):
    model = model # where the Elixir mappers are
    forms = forms # module containing FormAlchemy fieldsets definitions
    # # Uncomment this to impose an authentication requirement
    # @authorize(SignedIn())
    # def __before__(self):
    #     pass
    def Session(self): # Session factory
        return meta.Session

AdminController = FormAlchemyAdminController(AdminController)

(Note the commented-out code for access-protecting the Pylons Admin controller. Uncommenting the code will cause requests made of /admin resources to be automatically redirected to a login page and, upon successful authentication, will be automatically redirected to the originally-requested resource.)

The routing is simple and straighforward:

from formalchemy.ext.pylons import maps # routes generator

# [ ... ]

# CUSTOM ROUTES HERE

# Map the /admin url to FA's AdminController
# Map static files
map.connect('fa_static', '/jquery/{path_info:.*}',
            controller='jquery')
# Index page
map.connect('admin', '/admin',
            controller='admin', action='models')
map.connect('formatted_admin', '/admin.json',
            controller='admin', action='models', format='json')
# Models
map.resource('model', 'models', path_prefix='/admin/{model_name}',
             controller='admin')

The form templating engine (by default Tempita but in this instance, Mako) is initialised and the JQuery-supported fieldset and grid form holders are all defined in MYPROJ/form/__init__.py:

from pylons import config
from fatest import model
from fatest.lib.base import render
from formalchemy import config as fa_config
from formalchemy import templates
from formalchemy import validators
from formalchemy import fields
from formalchemy import forms
from formalchemy import tables
from formalchemy.ext.fsblob import FileFieldRenderer
from formalchemy.ext.fsblob import ImageFieldRenderer
from fa.jquery import renderers as jquery

if config.get('storage_path'):
    # set the storage_path if we can find its setting
    FileFieldRenderer.storage_path = config.get('storage_path')
    ImageFieldRenderer.storage_path = config.get('storage_path')

fa_config.encoding = 'utf-8'

class TemplateEngine(templates.TemplateEngine):
    def render(self, name, **kwargs):
        return render('/forms/%s.mako' % name, extra_vars=kwargs)
fa_config.engine = TemplateEngine()

# use jquery renderers
forms.FieldSet.default_renderers.update(jquery.default_renderers)

class FieldSet(forms.FieldSet):
    pass

class Grid(tables.Grid):
    pass

## Initialize fieldsets

User = FieldSet(model.User)
User.configure(options=[User.created.readonly()])

UserAdd = FieldSet(model.User)
UserAdd.configure(exclude=[UserAdd.created])

## Initialize grids

UserGrid = Grid(model.User)
UserGrid.configure(include=[
    UserGrid.username,
    UserGrid.email,
    UserGrid.active,
    UserGrid.groups,
    ])

A set of FA’s CSS grid-styled Mako templates are installed into the myproj/templates directory and the application is immediately ready for use.

Screenshots

View of the Shabti standard identity model

../_images/shabti_formalchemy_admin.jpg

View of the User admin page

../_images/shabti_formalchemy_user_index.jpg

Editing an existing User entity

../_images/shabti_formalchemy_user_edit.jpg

Creating a new user entity

../_images/shabti_formalchemy_user_new.jpg

See also

Form structure, content and appearance can all be customized. For details on how to customize the forms and the fields, see the docs for the Formalchemy Pylons extension

TODO

  1. Adjust the generation of the form so that password fields are presented unpopulated.
  2. Find out why the 2 authentication tests fail.
  3. Add a more extensive example, demonstrating more of FormAlchemy’s features.
  4. Add FormAlchemy and the CouchDBkit Formalchemy extension to the Shabti auth_couchdb template.
author:Graham Higgins <gjh@bel-epa.com>

September 06, 2010