Posts tagged ‘map’

Last Friday I came back from a 10 day road trip driving from San Francisco to Seattle, and coming back with the Amtrak Coast Starlight train – as I mentioned earlier.

I used Foursquare a bit more than usual (about 50 checkings over 10 days) and took a lot of pictures of rocks, landscapes, forests, the ocean, etc.
I started making a simple mashups to visualize the overall itinerary I ended up doing.

View full screen (Pink bubbles have photos. Blue bubbles are the checkins on the way to Seattle. Yellow bubbles are the checkins on the way back to San Francisco.)

I have photos on Flickr.

Some highlights:

  • 1990 miles / 3200 km driven from SF to Seattle in 8 days.
  • Very nice weather except the day I drived through Crater Lake, which I could not see at all because of the fog.
  • Not many tourists or anyone on the roads end of October.
  • I loved all the coastal areas, and especially the Olympic National Park.
  • I ended up staying in campgrounds most of the nights, in the middle of a forest or close to the ocean, with barely anyone around. That was awesome.
  • It’s not easy to find the cheap / non-RV campgrounds where you can put a tent or just sleep in the car.
  • All the roads were surprisingly well maintained (I’m too used to the bad roads of south SF).
  • I really liked the cities of Bend and Portland in Oregon. Seattle, WA… not as much but that was at the end of my trip. Redding, CA was weird.
  • I think I expected a bit more from the train trip (23 hours from Seattle to San Francisco). That was really comfortable but as I was into a good book, and we were going through areas I had driven across, I did not pay much attention to the landscape.

I put the code for the mashup on github.

 

  • 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,