In this module you are going to learn how to use the framework to create MapFish web services in your application.
MapFish web services are web services for creating, reading, updating and deleting geographic objects (features) through the MapFish Protocol.
The MapFish Protocol is a collection of HTTP APIs. It is highly recommended to take some time to go through the description of these APIs [1] before moving on with the rest of this module.
A MapFish web service relies on a geographic data table.
Note
Only PostgreSQL/PostGIS tables are currently supported by MapFish. There’s currently work being done to support SQLite/Spatialite and MySQL.
Before creating the web service we need to create a PostGIS table with some data into it. You’re going to create a PostGIS table from a Shapefile of countries.
First, open the explorer, go into the C:\MapFish\mapfish_workshop\data folder and extract the countries.zip file.
Create a PostGIS-enabled database named mapfish_workshop, and enter the following commands to import the countries Shapefile as a table named countries in the mapfish_workshop database:
C:\MapFish>cd mapfish_workshop\data
C:\MapFish\mapfish_workshop\data>"C:\Program Files\PostgreSQL\8.3\bin\ shp2pgsql.exe" -s 4326 -I countries.shp countries | "C:\Program Files\PostgreSQL\8.3\bin\psql.exe" -d mapfish_workshop -U postgres
You can start pgAdmin and connect to the mapfish_workshop database to check that the countries table is present and non-empty.
You now need to set up the connection to the mapfish_workshop database from MapFishApp. This is done in the development.ini file.
Edit development.ini and replace the line
sqlalchemy.url = sqlite:///%(here)s/development.db
by this one:
sqlalchemy.url = postgres://postgres:postgres@localhost:5432/mapfish_workshop
The connection string specifies that the postgres driver must be used, the database system listens on localhost and on port 5432, and the name of the database is mapfish_workshop.
Now that the table is created and the connection to the database is set up, you’re ready to create the web service.
Creating a web service is done in three steps:
create a layer configuration in the layers.ini file, in our case:
[countries]
singular=country
plural=countries
table=countries
epsg=4326
geomcolumn=the_geom
singular provides a singular name for the layer. plural provides a plural name for the layer. Both are used by the code generator when substituting variables. table provides the name of the database. epsg provides the coordinate system of the table data. geomcolumn provides the name of the geometry column.
generate the web service code with the mf-layer command:
<env> C:\MapFish\MapFishApp>paster mf-layer countries
configure a route to the countries controller, this is done by adding the following statement after the “CUSTOM ROUTES HERE” comment in the mapfishapp/config/routing.py file:
map.resource("country", "countries")
Watch the indentation! 4 spaces are needed here.
If you killed paster serve or if you did not add the --reload switch, restart MapFishApp with:
<env> C:\MapFish\MapFishApp>paster serve --reload development.ini
You can now open http://localhost:5000/countries?limit=1 in your browser, you should see a GeoJSON representation of the first object in the countries table:
Bonus task
Open the MapFish Protocol description again and write the URLs for the following queries:
The paster mf-layer countries created three Python files:
This file includes the controller code of the countries web service. This is the core of the web service.
class CountriesController(BaseController):
readonly = False # if set to True, only GET is supported
def __init__(self):
self.protocol = Protocol(Session, Country, self.readonly)
def index(self, format='json'):
"""GET /: return all features."""
return self.protocol.index(request, response, format=format)
def show(self, id, format='json'):
"""GET /id: Show a specific feature."""
return self.protocol.show(request, response, id, format=format)
def create(self):
"""POST /: Create a new feature."""
return self.protocol.create(request, response)
def update(self, id):
"""PUT /id: Update an existing feature."""
return self.protocol.update(request, response, id)
def delete(self, id):
"""DELETE /id: Delete an existing feature."""
return self.protocol.delete(request, response, id)
The controller has methods for each protocol operation: get features (index), get a feature (show), create features (create), update a feature (update), and delete a feature (delete). These methods all rely on Protocol object, this protocol object includes all the logic of the MapFish Protocol as defined in the description.
This file includes the model code of the countries web service. The model defines the countries table object, the Country class representing a table record, and the mapping between the two.
countries_table = Table(
'countries', metadata,
Column('the_geom', Geometry(4326)),
autoload=True, autoload_with=engine)
class Country(GeometryTableMixIn):
# for GeometryTableMixIn to do its job the __table__ property
# must be set here
__table__ = countries_table
mapper(Country, countries_table)
The code generated by the paster mf-layer belongs to the application developer. The developer is free to modify it, based on his needs.
[1] | http://www.mapfish.org/doc/1.2/protocol.html |