June 28, 2023, by Paolo Melchiorre
Since ancient times, maps have always allowed to seek and find information in "spatial mode". Today it is very common for them to be inserted into websites, as we did in the case of Mer et Demeures.
A web map is the representation of a geographical system, providing spatial data and information.
The map can have different features, depending on what is needed:
We used 3 fundamental software components for Mer et Demeures: GeoDjango, PostGIS and Leaflet JS. Let's see them one at a time.
This one is not an external package, on the contrary it has been part of Django, as a contrib package, since version 1.0: it turns Django, as we were saying, into a geographic spatial framework.
How does it work?
First of all, GeoDjango provides us with spatial field types - there is quite a few of them - and allows us to perform spatial queries directly in Django’s ORM. Also, the fields are already integrated into the admin.
GeoDjango currently supports 4 geospatial databases.
We used PostGIS in this project: we opted for it because we were already using PostgreSQL, but also because it represents GeoDjango’s backend with the most extensive support.
This is a PostgreSQL extension which directly integrates spatial data.
Alongside with GeoDjango, PostGIS provides us with specific data types so as to store our spatial information. In addition, there are indexes optimized for spatial data, as well as specific functions that we can use to search for this kind of data.
We added Leaflet to our stack, for the frontend map, for a number of reasons.
Another aspect of primary importance, both for the client and for us developers, consists in the fact that it is a Free Software, with a large community of developers participating in its development. Moreover, it is mobile friendly, which is essential in the present era, and it is also very light.
Plus, it is extremely easy to use: the documentation is accessible and the result you get has excellent performance.
Let's take Django’s Blog application, which can be found in the documentation, and test it with these three models.
We are going to add spatial data to this application and render them in a web map. Starting from this example, the first step is to change the settings:
We should also activate the PostGIS extension with a migration:
The other change we need to make is adding a PointField, importing it from GeoDjango. We have also added a property, which will then be useful in Leaflet, so as to render longitude and latitude.
The easiest way to change our entries consists in changing Admin in order to use a specific one. We can also indicate distinct attributes and zoom by default.
The end result is a map that you can interact with: you can zoom in and out and move around, all using a few lines of code.
Once we have edited the entries and added points to the admin, we can show them on a real map. We use views and urls to do this:
After defining the EntryList, we map it to a url: and here is where the backend work ends. The following step concerns writing the template.
We then insert a loop with the list of markers and we ask Leaflet to print one with latitude and longitude for each marker.
This code is actually working: you can try using it too, by following all the steps!
WARNING: PostGIS first asks for longitude and then latitude, while Leaflet, on the contrary, first asks for latitude and then longitude. That is why we have created a property.
Compared to what we have just seen, the situation we have faced in this product is much more complex and requires a more detailed approach.
Mer et Demeures is a French company, based in Provence, selling and renting properties by the sea all over the world. Being active since 2014, it has a portal, which has been translated into 8 languages, with over 100,000 ads in 40 countries and 6 continents.
This massive work had already been in production for a long time and required a very complex and interactive map.
To understand the difference in comparison with the basic examples above, here is an excerpt of the models.
For example, we used the multipolygon to display city boundaries, the ad model with a PointField and a much more complex hierarchy.
We couldn’t use a template for this project, but we decided to implement a RESTful API and provide it to the frontend.
The first step for implementing an API is to write a model serializer: we inherited a basic one, in which we specified model, field and additional fields.
The next step consisted in importing a view:
At this point we use DefaultRouter and shut the backend work.
The result is a GeoJSON, a standard way of providing geo-spatial data:
Here there are no additional properties, but there were several in the original project, so as to render pop-ups with additional data (such as currency, price...).
At this point the ball is in the frontend’s court, which will be able to query these data.
The main difference, compared to the previous procedure, is that the GeoJSON can contain polygons, markers, basically anything that respects its standards: this way we are able to render everything in one shot.
Leaflet also provides events: we were interested in Moveend, to be invoked when the centre of the map is moved and when animations end. This is a very useful aspect in case of strong interaction with the map, as for Mer et Demeures.
As for what concerns the React part, we used a React Leaflet, which is not a separate library but only a station (that is why Leaflet needs to be installed too):
We import React and the 3 components provided by the library and we initialize the state of our component in a new GeoJSON object, where all the new contents will be placed. Then there is the function that is invoked at the time of interaction.
Let’s see the Render method, which is very similar to the other:
In our case we really had many ads to place and it is not recommended to render more than 100 markers on Leaflet because it slows it down a lot.
The solution we foundconsisted in clustering these markers on the backend side which expanded when the user clicked: on React this thing severely slowed down rendering.
In conclusion, these are the highlights of our work:
A special thanks to Mer et Demeures who allowed us to study and explore such an interesting topic, thanks to their product!