• Install the packages:
% pip install FormAlchemy fa.query GeoFormAlchemy
1
% pip install FormAlchemy fa.query GeoFormAlchemy
  • You have now more templates available:
% paster create --list-templates
  basic_package:   A basic setuptools-enabled package
  geo_fa:          Pylons application template with GeoFormAlchemy support
  mapfish:         MapFish application template
  mapfish_client:  MapFish client plugin template
  paste_deploy:    A web application deployed through paste.deploy
  pylons:          Pylons application template
  pylons_fa:       Pylons application template with formalchemy support
  pylons_minimal:  Pylons minimal application template
1
2
3
4
5
6
7
8
9
% paster create --list-templates
  basic_package:   A basic setuptools-enabled package
  geo_fa:          Pylons application template with GeoFormAlchemy support
  mapfish:         MapFish application template
  mapfish_client:  MapFish client plugin template
  paste_deploy:    A web application deployed through paste.deploy
  pylons:          Pylons application template
  pylons_fa:       Pylons application template with formalchemy support
  pylons_minimal:  Pylons minimal application template
  • You can run the command to add some of the GeoFormAlchemy or the formalchemy support to your project:
% paster create -t geo_fa
1
% paster create -t geo_fa

Keep the default values except for the first one

Enter admin_controller (Add formalchemy's admin controller) [False]: True 
1
Enter admin_controller (Add formalchemy's admin controller) [False]: True 

And answer no unless  you want to overrite a file:

Overwrite ./MyApp/myapp/config/environment.py [y/n/d/B/?] n
[etc ...]
1
2
Overwrite ./MyApp/myapp/config/environment.py [y/n/d/B/?] n
[etc ...]
  • If you do not run the paster create command, you’ll have to add those files directly:
    • Add the file
      myapp/controllers/admin.py
    • Add the file
      myapp/forms/__init__.py
    • Add the template files in (on githhub-FormAlchemy and github-GeoFormAlchemy)
      myapp/templates/forms/ fieldset.mako, 
      fieldset_readonly.mako, grid.mako, grid_readonly.mako, map.mako, map_js.mako, 
      restfieldset.mako
    • Modify
      myapp/config/routing.py
  • Add the admin controller
    myapp/controllers/admin.py
### myapp/controllers/admin.py
import logging
from formalchemy.ext.pylons.controller import ModelsController
from webhelpers.paginate import Page
from myapp.lib.base import BaseController, render
from myapp import model
from myapp import forms
from myapp.model import meta

log = logging.getLogger(__name__)

class AdminControllerBase(BaseController):
    model = model # where your SQLAlchemy mappers are
    forms = forms # module containing FormAlchemy fieldsets definitions
    def Session(self): # Session factory
        return meta.Session

    ## customize the query for a model listing
    # def get_page(self):
    #     if self.model_name == 'Foo':
    #         return Page(meta.Session.query(model.Foo).order_by(model.Foo.bar)
    #     return super(AdminControllerBase, self).get_page()

AdminController = ModelsController(AdminControllerBase,
                                   prefix_name='admin',
                                   member_name='model',
                                   collection_name='models',
                                  )
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
### myapp/controllers/admin.py
import logging
from formalchemy.ext.pylons.controller import ModelsController
from webhelpers.paginate import Page
from myapp.lib.base import BaseController, render
from myapp import model
from myapp import forms
from myapp.model import meta

log = logging.getLogger(__name__)

class AdminControllerBase(BaseController):
    model = model # where your SQLAlchemy mappers are
    forms = forms # module containing FormAlchemy fieldsets definitions
    def Session(self): # Session factory
        return meta.Session

    ## customize the query for a model listing
    # def get_page(self):
    #     if self.model_name == 'Foo':
    #         return Page(meta.Session.query(model.Foo).order_by(model.Foo.bar)
    #     return super(AdminControllerBase, self).get_page()

AdminController = ModelsController(AdminControllerBase,
                                   prefix_name='admin',
                                   member_name='model',
                                   collection_name='models',
                                  )
  • Modify
    myapp/config/routing.py
### In myapp/config/routing.py
    # Map the /admin url to FA's AdminController
    # Map static files
    map.connect('fa_static', '/admin/_static/{path_info:.*}', controller='admin', action='static')
    # 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')
1
2
3
4
5
6
7
8
9
### In myapp/config/routing.py
    # Map the /admin url to FA's AdminController
    # Map static files
    map.connect('fa_static', '/admin/_static/{path_info:.*}', controller='admin', action='static')
    # 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')
  • myapp/forms/__init__.py
### myapp/forms/__init__.py
from pylons import config
from myapp.model import my_app_points
from myapp.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 geoformalchemy.base import GeometryFieldRenderer
from geoalchemy import geometry
forms.FieldSet.default_renderers[geometry.Geometry] = GeometryFieldRenderer

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()
class FieldSet(forms.FieldSet):
    pass
class Grid(tables.Grid):
    pass
## Initialize fieldsets
#Foo = FieldSet(model.Foo)
#Reflected = FieldSet(Reflected)
## Initialize grids
#FooGrid = Grid(model.Foo)
#ReflectedGrid = Grid(Reflected)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
### myapp/forms/__init__.py
from pylons import config
from myapp.model import my_app_points
from myapp.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 geoformalchemy.base import GeometryFieldRenderer
from geoalchemy import geometry
forms.FieldSet.default_renderers[geometry.Geometry] = GeometryFieldRenderer

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()
class FieldSet(forms.FieldSet):
    pass
class Grid(tables.Grid):
    pass
## Initialize fieldsets
#Foo = FieldSet(model.Foo)
#Reflected = FieldSet(Reflected)
## Initialize grids
#FooGrid = Grid(model.Foo)
#ReflectedGrid = Grid(Reflected)
  • To test, restart you server, and open and refresh
    /admin

    . Unless you’ve added models in your

    myapp/models/__init__.py

    , you won’t see any link to the models.

Adding a model to the Admin view

One of my models
myapp/model/my_app_points.py

was defined as such

###myapp/model/my_app_points.py 
from sqlalchemy import Column, types
from geoalchemy import GeometryColumn, Point
from mapfish.sqlalchemygeom import GeometryTableMixIn
from mapfishapp.model.meta import Session, Base

class MyAppPoint(Base, GeometryTableMixIn):
    autoload_with = Session.bind
    __tablename__ = 'my_app_point'
    __table_args__ = {
        "autoload_with": Session.bind,
        "autoload": True,
    }
    way = GeometryColumn(Point(srid=900913))
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
###myapp/model/my_app_points.py 
from sqlalchemy import Column, types
from geoalchemy import GeometryColumn, Point
from mapfish.sqlalchemygeom import GeometryTableMixIn
from mapfishapp.model.meta import Session, Base

class MyAppPoint(Base, GeometryTableMixIn):
    autoload_with = Session.bind
    __tablename__ = 'my_app_point'
    __table_args__ = {
        "autoload_with": Session.bind,
        "autoload": True,
    }
    way = GeometryColumn(Point(srid=900913))

I’d get an error by importing that class in

myapp/model/__init__.py
from myapp.models.my_app_points import MyAppPoint
1
from myapp.models.my_app_points import MyAppPoint

would lead to that error:

sqlalchemy.exc.UnboundExecutionError: No engine is bound to this Table's MetaData.
Pass an engine to the Table via autoload_with=<someengine>, or associate the MetaData
with an engine via metadata.bind=<someengine>
1
2
3
sqlalchemy.exc.UnboundExecutionError: No engine is bound to this Table's MetaData.
Pass an engine to the Table via autoload_with=<someengine>, or associate the MetaData
with an engine via metadata.bind=<someengine>

Modifying myapp/model/__init__.py by adding Base.metadata.bind = engine at the end of init_model(engine) did not work.

The solution I found after checking the formalchemy code was to modify the myapp/controllers/admin.py and pass a list of the model classes to list in the web admin view.

###Modify in myapp/controllers/admin.py
from myapp.model.my_app_points import MyAppPoint

list_models = [MyAppPoint,]
class AdminControllerBase(BaseController):
    model = list_models # where your SQLAlchemy mappers are
    forms = forms # module containing FormAlchemy fieldsets definitions
1
2
3
4
5
6
7
###Modify in myapp/controllers/admin.py
from myapp.model.my_app_points import MyAppPoint

list_models = [MyAppPoint,]
class AdminControllerBase(BaseController):
    model = list_models # where your SQLAlchemy mappers are
    forms = forms # module containing FormAlchemy fieldsets definitions

And finally you can add something like that at the end of your

myapp/forms/__init__.py
MyAppPoint = FieldSet(my_app_points.MyAppPoint)
MyAppPoint.configure(options=[MyAppPoint.way.label('Geometry').required()])
MyAppPoint.way.set(options=[
        ('map_srid', 900913),
        ('base_layer', 'new OpenLayers.Layer.OSM("OSM")'),
        ('openlayers_lib', '/lib/openlayers/lib/OpenLayers.js'),
        ('zoom', 14)
    ])
1
2
3
4
5
6
7
8
MyAppPoint = FieldSet(my_app_points.MyAppPoint)
MyAppPoint.configure(options=[MyAppPoint.way.label('Geometry').required()])
MyAppPoint.way.set(options=[
        ('map_srid', 900913),
        ('base_layer', 'new OpenLayers.Layer.OSM("OSM")'),
        ('openlayers_lib', '/lib/openlayers/lib/OpenLayers.js'),
        ('zoom', 14)
    ])

 

Sources: mapfish-geoformalchemy,