Dans ce module vous allez apprendre à utiliser le Framework pour créer le Service Web MapFish au sein de votre application.
Les services Web de MapFish sont des services permettant de créer, de lire, de mettre à jour et de supprimer des entités géographiques au travers du Protocole MapFish.
Le protocole MapFish est une collection d’APIs de type HTTP. Il est fortement recommandé de prendre le temps de parcourir la description de ces APIs [1] avant de poursuivre ce module.
Un service web MapFish repose sur des sources de données géo-spatiales.
Avant de concevoir le service web nous devons créer une table PostGIS contenant des données. Vous allez donc créer une table PostGIS à partir d’un Shapefile des pays.
D’abord, créez une base de données PostGIS que vous nommerez mapfish_tutorial. Pour cela vous pouvez lancer les commandes suivantes :
$ sudo su - postgres
$ createdb mapfish_tutorial
$ createlang plpgsql mapfish_tutorial
$ psql -d mapfish_tutorial -f /usr/share/postgresql/8.4/contrib/postgis-1.5/postgis.sql
$ psql -d mapfish_tutorial -f /usr/share/postgresql/8.4/contrib/postgis-1.5/spatial_ref_sys.sql
Note
Les commandes ci-dessus supposent PostgreSQL 8.4 and PostGIS 1.5, elles sont donc à adapter en fonction des versions de PostgreSQL and PostGIS installées sur votre système. Par exemple, avec PostgreSQL 8.3, les deux dernières seraient comme suit sur un système Debian :
$ psql -d mapfish_tutorial -f /usr/share/postgresql-8.3-postgis/lwpostgis.sql
$ psql -d mapfish_tutorial -f /usr/share/postgresql-8.3-postgis/spatial_ref_sys.sql
Puis téléchargez le shapefile zippé disponible sur le site mapfish.org, et décompressez le :
$ wget http://www.mapfish.org/svn/mapfish/sandbox/camptocamp/mapfish_workshop/data/countries.zip
$ unzip countries.zip
Puisque notre application fonctionnera dans la projection Google Spherical Mercator, reprojetons (et simplifions un petit peu ces géométries) grâce à la commande très utile, ogr2ogr et shp2pgsql :
$ ogr2ogr -t_srs EPSG:900913 -segmentize 2000 countries-900913.shp countries.shp
puis en tant qu’utilisateur postgres, importez le dans la base mapfish_tutorial :
$ shp2pgsql -s 900913 -I countries-900913.shp countries | psql -d mapfish_tutorial
Créez un utilisateur pour la base de données, nommé mapfish avec le mot de passe mapfish par exemple :
$ createuser --no-superuser --no-createdb --no-createrole mapfish
$ psql -c "ALTER USER mapfish WITH PASSWORD 'mapfish';"
$ psql -d mapfish_tutorial -c "GRANT ALL ON TABLE countries TO mapfish;"
$ psql -d mapfish_tutorial -c "GRANT ALL ON TABLE geometry_columns TO mapfish;"
Vous pouvez lancer psql et vous connecter à la base mapfish_tutorial pour vérifier que la table countries est présente et remplie.
Vous devez maintenant configurer la connexion à la base de données mapfish_tutorial depuis MapFishApp. Ceci peut être mis en œuvre en éditant le fichier development.ini.
Edit development.ini et remplacez cette ligne :
sqlalchemy.url = sqlite:///%(here)s/development.db
par celle-ci :
sqlalchemy.url = postgresql://mapfish:mapfish@localhost:5432/mapfish_tutorial
Ces différents arguments de connexion spécifient premièrement que le driver postgresql doit être utilisé, que la base de données écoute localhost sur le port 5432, et finalement que notre base de données s’appelle mapfish_tutorial.
Maintenant que la table est crée et que la connexion à la base de données est opérationnelle, vous êtes prêts pour concevoir le service web.
La création du service web est établie en trois étapes :
1. Créer la configuration des couches au sein du fichier layers.ini, dans notre cas :
[countries]
singular=country
plural=countries
table=countries
epsg=900913
geomcolumn=the_geom
geomtype=MultiPolygon
``singular`` donne le nom au ``singulier`` de la couche. ``plural`` donne
le nom au pluriel de la couche. Les deux sont utilisés par le générateur de
code lors de la substitution des variables. ``table`` donne le nom de la table.
``epsg`` donne le système de coordonnées utilisé par la donnée de la table.
``geomcolumn`` donne le nom de la colonne contenant l’information géométrique.
Générer le service web en utilisant la commande mf-layer
$ paster mf-layer countries
mis en œuvre en ajoutant ces lignes après le commentaire “CUSTOM ROUTES HERE” dans le fichier mapfishapp/config/routing.py :
map.connect("/countries/count", controller="countries", action="count")
map.resource("country", "countries")
votre controleur. Assure vous de rajouter ces lignes AVANT le map.resource précédent ... :
map.connect('/countries/count', controller='countries', action='count')
map.resource("country", "countries")
Attention à l’indentation ! 4 espaces sont ici indispensables.
Si vous avez tué paster serve ou si vous n’avez pas ajouté le paramètre --reload, redémarrez MapFishApp avec :
$ paster serve --reload development.ini
Vous pouvez à présent ouvrir http://localhost:5000/countries?limit=1 avec votre navigateur, vous devriez apercevoir une représentation GeoJSON du premier objet de la table countries :
Bonus
Ouvrez le Protocole MapFish description puis saisissez y les URLs correspondantes aux requêtes suivantes :
La commande paster mf-layer countries génère trois fichiers Python:
Ce premier fichier comprend le code-contôleur du service web countries Il s’agit là du cœur du service web.
class CountriesController(BaseController):
readonly = False # if set to True, only GET is supported
def __init__(self):
self.protocol = Protocol(Session, Country, self.readonly)
@geojsonify
def index(self, format='json'):
"""GET /: return all features."""
if format != 'json':
abort(404)
return self.protocol.read(request)
@geojsonify
def show(self, id, format='json'):
"""GET /id: Show a specific feature."""
if format != 'json':
abort(404)
return self.protocol.read(request, response, id=id)
@geojsonify
def create(self):
"""POST /: Create a new feature."""
return self.protocol.create(request, response)
@geojsonify
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)
def count(self):
"""GET /count: Count all features."""
return self.protocol.count(request)
Le contrôleur possède des méthodes pour chaque opérations du protocole : obtenir les entités (index), obtenir une entité (show), créer une entité (create), mettre à jour une entité (update), et supprimer une entité (delete). Ces méthodes reposent toutes sur l’objet Protocol, ce dernier comprend l’ensemble logique du Protocole MapFish comme le définis sa description.
Ce fichier comprend le modèle du code du service web countries. Ce modèle définit l’objet de la table countries, la classe Country représentant un enregistrement de la table, et la cartographie entre ces deux.
class Country(Base, GeometryTableMixIn):
__tablename__ = 'countries'
__table_args__ = {
"autoload": True,
"autoload_with": Session.bind
}
the_geom = GeometryColumn(MultiPolygon(srid=900913))
Le code généré par la commande paster mf-layer dépend du développeur de l’application. Ce dernier est libre de la modifier selon ses propres besoins.
[1] | http://www.mapfish.org/doc/2.0/protocol.html |