Table Of Contents

Previous topic

Module 4 - Construction de scripts JavaScript

Next topic

Module 6 - Ajout de la fonctionnalité de recherche

This Page

Module 5 – Création du service Web

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.

Installation des données

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.

Connexion à la base de données

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.

Création du service web

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.
  1. Générer le service web en utilisant la commande mf-layer

    $ paster mf-layer countries
  2. Configurer une route vers le contrôleur countries, ce dernier peut être

    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")
    
  3. vous pouvez ajouter une route pour compter les lignes sur la table mappée de

    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 :

../images/geojson.png

Bonus

Ouvrez le Protocole MapFish description puis saisissez y les URLs correspondantes aux requêtes suivantes :

  • Obtenir le pays dont l’identifiant est 1
  • Obtenir le pays contenant le point (5, 45)
  • Obtenir le pays contenant le point (5, 45), sans récupérer sa géométrie
  • Obtenir le pays contenant le point (5, 45) en ne récupérant que les attributs pays et population

Etudions le code du service web

La commande paster mf-layer countries génère trois fichiers Python:

mapfishapp/controllers/countries.py

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.

mapfishapp/model/countries.py

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))
tests/functional/test_countries.py
Ce fichier est l’emplacement où le développeur de l’application peu déposer ses tests fonctionnels pour le service web countries. Il est initialement vide.

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