Table Of Contents

Previous topic

TileCache

Next topic

Workshop Python (version française)

This Page

MapFish

MapFish is a flexible and complete framework for building rich web-mapping applications. It emphasizes high productivity, and high-quality development.

MapFish combines the power of Pylons, SQLAlchemy, GeoAlchemy, Shapely, and geojson.

In this module you will learn about what the MapFish framework provides, and how it simplifies the development of web services for querying and editing geographic features.

Install

To install MapFish in the virtual Python environment use:

(vp) $ easy_install "MapFish==2.0"

You should now have MapFish installed. You can check that using this command:

(vp) $ paster create --list-templates

This command should output this:

Available templates:
basic_package:   A basic setuptools-enabled package
mapfish:         MapFish application template
paste_deploy:    A web application deployed through paste.deploy
pylons:          Pylons application template
pylons_minimal:  Pylons minimal application template

Note the mapfish line.

Upgrade application

In this section you’re going to convert your application from a Pylons application into a MapFish application. A MapFish application is a Pylons application with extra, MapFish-specific, features.

Edit setup.py and add MapFish to the list of paster plugins:

paster_plugins=['MapFish', 'PasteScript', 'Pylons'],

Now execute:

(vp) $ python setup.py egg_info

This registers MapFish as a paster plugin, which will allow you to use MapFish-specific commands for the development of the application. You will learn more about that later in this module.

You can check that your application is now a MapFish application by typing:

(vp) $ paster

And verify that the output of the command includes the following block:

mapfish:
  mf-controller   Create a MapFish controller and accompanying functional test
  mf-layer        Create a MapFish layer (controller + model).
  mf-model        Create a MapFish model

mf-controller, mf-layer, and mf-model are commands provided by the MapFish framework.

Create a MapFish web service

In this section you’re going to create a MapFish web service that relies on the summits table. You will thereby understand what MapFish actually brings to the developer.

Create the file layers.ini at the root of your application, with this content:

[mfsummits]
singular=mfsummit
plural=mfsummits
table=summits
epsg=4326
geomcolumn=geom
geomtype=Point

and execute this command:

(vp) $ paster mf-layer mfsummits


Creating /home/python/python_workshop/WorkshopApp/workshopapp/controllers/mfsummits.py
Creating /home/python/python_workshop/WorkshopApp/workshopapp/tests/functional/test_mfsummits.py

To create the appropriate RESTful mapping, add a map statement to your
config/routing.py file in the CUSTOM ROUTES section like this:

map.resource("mfsummit", "mfsummits")

Creating /home/python/python_workshop/WorkshopApp/workshopapp/model/mfsummits.py

As indicated in the command ouput edit the workshopapp/config/routing.py file and add an appropriate route by inserting map.resource("mfsummit", "mfsummits"). Insert this route before the default routes, for example right after the tilecache route.

You can now verify that your MapFish web service functions properly. For example open http://localhost:5000/mfsummits?limit=2 in FireFox. But in fact, because a model class already exists for the table summits, SQLAlchemy will produce an error:

../images/summits_already_defined_error.png

To correct the error edit workshopapp/model/mfsummits.py and add useexisting: True in the table arguments (__table_args__):

from sqlalchemy import Column, types

from geoalchemy import GeometryColumn, Point

from mapfish.sqlalchemygeom import GeometryTableMixIn
from workshopapp.model.meta import Session, Base

class Mfsummit(Base, GeometryTableMixIn):
    __tablename__ = 'summits'
    __table_args__ = {
        "autoload": True,
        "autoload_with": Session.bind,
        "useexisting": True
    }
    geom = GeometryColumn(Point(srid=4326))

Open http://localhost:5000/mfsummits?limit=2 again in the browser.

Play with the MapFish web service

MapFish implements HTTP interfaces for querying and editing features. Any MapFish web service, i.e. any web service created with the paster mf-layer command implements these interfaces. These interfaces are documented in http://trac.mapfish.org/trac/mapfish/wiki/MapFishProtocol.

Create

To create new features the HTTP POST method is used. As an example you can enter the following curl command in your terminal:

curl http://localhost:5000/mfsummits -X POST -H 'Content-Type:"application/json"' \
-d '{"type": "FeatureCollection",
     "features": [{"type": "Feature", "geometry": {"type": "Point", "coordinates": [5.8, 45.3]}}]}'

The command should output something like this:

{"type": "FeatureCollection",
 "features": [{"geometry": {"type": "Point",
                            "coordinates": [5.7999999999999998, 45.299999999999997]},
               "id": 5081, "type": "Feature",
               "bbox": [5.7999999999999998, 45.299999999999997,
                        5.7999999999999998, 45.299999999999997],
               "properties": {"elevation": null, "name": null}}]}

Note that GeoJSON response include the identifiers of the created features. In this example, one feature was created, its id is 5081.

Now open http://localhost:5000/mfsummits/<id> in the browser to get a GeoJSON representation of the freshly created feature, and verify that it has indeed been inserted in the database. <id> is to be replaced with the actual feature identifier (5081 in this example).

Update

To update a feature the HTTP PUT method is used. As an example use this curl command:

curl http://localhost:5000/mfsummits/<id> -X PUT -H 'Content-Type:"application/json"' \
-d '{"type": "Feature", "geometry": {"type": "Point", "coordinates": [6.0, 46]},
     "properties": {"name": "foo", "elevation": 1000}}'

Again replace <id> by the actual feature identifier (5081 in the above example).

The command should output something like this:

{"geometry": {"type": "Point", "coordinates": [6.0, 46.0]}, "id": 5081, "type": "Feature",
 "bbox": [6.0, 46.0, 6.0, 46.0], "properties": {"elevation": 1000, "name": "foo"}}

Again you can open http://localhost:5000/mfsummits/<id> in the browser to verify that the feature has been updated as expected.

Delete

To delete a feature the HTTP DELETE method is used. For example to delete with the curl command the feature whose id is 5081:

curl http://localhost:5000/mfsummits/<id> -X DELETE

If you open http://localhost:5000/mfsummits/<id> in the browser you should now get a 404 error.