Hypermedia driven maps

This video features Andrea Guerra at Django Day Copenhagen 2024 in Copenhagen, Denmark.

Hypermedia driven maps
0:32:08
Published October 13, 2024
260 views

Django Day Copenhagen 2024 talk descriptions: https://2024.djangoday.dk/

Summary

Andrea Guerra demonstrates a simple Django map built around hypermedia: Django renders HTML fragments and GeoJSON, while HTMX swaps those fragments without reloading the page and Leaflet remains an interactive map island. The example uses Django GeoJSON with a lightweight location model, avoiding PostGIS and heavier GIS dependencies for basic markers. A single persistent map updates its markers when users navigate between list and detail views, and map clicks set latitude and longitude in an edit form. Guerra presents this as a proof of concept for keeping basic map features simple, while noting that tasks such as drawing polygons may justify a library like Django Leaflet.

Key takeaways

  • Hypermedia can update selected HTML fragments with HTMX, avoiding full-page reloads while keeping most application rendering on the server.
  • Leaflet can function as an interactive map island alongside Django-rendered interface and data.
  • Django GeoJSON can serialize location points and popup content without requiring PostGIS or GDAL for this basic example.
  • HTMX swaps update the map by reading fresh GeoJSON from the page and replacing its marker layer, while retaining the same map instance.
  • Map clicks can populate latitude and longitude fields in an edit form; more involved mapping needs, such as polygon drawing, may call for dedicated widgets or libraries.

Summarised automatically from the transcript.

Transcript

4,008 words · auto-generated Show

Automatically transcribed, so expect mistakes in names and technical terms.

0:03

Speaker 1: Much further ado. I see people enjoying the coffee and the tea shouldn't have mentioned that. And the stick.

0:13

Speaker 2: And the stickers.

0:16

Speaker 1: Um but we should really get started. Um Five seconds. Mute yourselves. Okay. We're ready. On stage, Andrea, welcome. Please give Andrea a big hand.

0:43

Speaker 2: Do you hear me? Okay. So we will be talking about maps again, but uh just in a different uh kind of way because uh we've seen that uh Rosamund uh worked with uh React and uh I will work with uh hypermedia And I'm Andrea Guerra. Here you have some links of my projects, of my blog and so on. And I have to tell you that I'm not a developer, I'm an architect. So I normally design uh buildings. I uh design renovations and things like that. But I've been into programming since I was a teenager.

1:31

Speaker 2: From a time in which You didn't have floppy disk and you you have to load you had to load things with uh uh cassette cassette recorders And then I started a blog and 25 years ago. It was a pure HTML. And then it evolved in time, becoming WordPress. So I started learning PHP and then I noticed that Python was better. And so I shifted everything to Django. And now I'm very proud because in the last weeks I uh I released a Python project.

2:17

Speaker 2: in the PyPy repository, Django GeoCAD, which takes drawings from AutoCAD and brings it into web maps. And uh so I give my contribution to this uh okay hypermedia driven maps. Uh what is hypermedia? Here I have some quotes uh from uh uh the the author of uh HTMX uh uh Carson Gross and uh hypermedia was the the old way of making websites. You have uh you had multi page, you had uh everything Written in HTML tags and every time you had a request-response cycle

3:03

Speaker 2: you had to reload the page. So that was very annoying. And so then came the single page applications and the new hypermedia uh adds to uh normal hypermedia adds uh the the SPA flavor because it doesn't reload the whole page. It loads just uh small chunks of uh of HTML replacing in uh targets so to speak. So uh it looks like an SPA but in fact it's uh it's uh the the old way the old way of making uh uh websites. Another concept that that I borrow from uh uh from Carson

3:49

Speaker 2: is uh that of the island of interaction So inside our hypermedia application we can have some isolated islands of interaction which are normally in JavaScript. They live on the client. But they are in some way managed and uh controlled by the hypermedia. And of course in our case uh the the this island will be uh a leaflet uh a leaflet map like the one that uh Rosamund uh uh showed us before and uh I use uh for the um The swapping trick, I use uh HTMX, but there are also other

4:37

Speaker 2: uh libraries like Alpine or uh And poly and so on. I won't dig too much into HTMX because there will be a following uh talk about this so I will just scratch a little bit the the surface. The important thing is that we Zwap ch chunks, but we don't reload the page. This is uh the goal of everything now is to not reload the page. So this is how our hypermedia driven app will look like. We have uh in the orange frame we have uh we have the hypermedia part. the the part that will be swapped. And it has the content, it has the user interface, it has the data for the map.

5:26

Speaker 2: and it also brings state for for the the island of uh of interaction. On the right you have the the island And if of course you I show you an island at Scapri, if you haven't recognized it. And of course, this part is fully interactive. You can pan, you can zoom uh like you usually do uh with uh with uh a map uh when you have it on uh on on uh on a web uh a website. And here I show you the interactions that happen between all the all the moving parts let's say You see I have those black arrows. The big one goes from the hypermedia to the island.

6:12

Speaker 2: But sometimes the island will will give back something and then you will have the response uh the request-response cycle from our chunk to uh to the Django application and also the the the island will uh communicate with an external uh server that will download all the tiles that are that you need to make up the the the map, all the small tiles that make up the map. And you will see that you see I I have a a yellow uh a yellow arrow. Sometimes uh the island of interaction

6:57

Speaker 2: will uh send directly to the Django uh app will send uh some requests. So we we are talking about Django. Of course there is a Django project at the base of everything. And here are the requirements. I use the latest Django and apart from other not relevant libraries I use Django HTMX by Adam Johnson, which is uh very clever because uh it tells you when uh request comes from from HTMX. So you can recognize when HTMX is involved and so when you are expecting to swap a part of the of

7:43

Speaker 2: the page. And then I I use a Django GeoJSON, which is uh uh kind of a serializer, and it writes uh all the geographic data into a format with this which is called uh uh GeoJSON, which is a JSON in fact. And it's very interesting because it does not rely on postGis or not even Postgres. Not even GDAL, which is the basic library, which is written in in C<unk>. uh without the that library nothing works. But it's a little bit tricky to have it on on your uh

8:28

Speaker 2: uh on your system. So in this way I can have the lightest application possible And I I have an app, of course, which has uh just one model , which is called location and it holds uh the title, the description of the location, and then the point field uh which is taken from uh uh the GeoJSON uh uh package. It's a point field. It uh it writes in uh in GeoJSON format uh where is is located geographically uh the the location. Apart from this, there is another

9:16

Speaker 2: method pretty important which is called pop up pop-up content, and uh it uh uh returns uh an HTML string with the absolute URL URL of the location and the title of the location. And this will be useful because it will show up when we click on a marker and have the pop-up coming out. And um okay, we start uh we run the server Of course, this is the first time that we enter the website and a location list view is called. It's a generic list view

10:01

Speaker 2: with uh some little tweaks like example I override the get template names uh and uh Here is where uh Django HTMX come comes handy because if it's if it's not an HTMX request we just get the whole page, the full page But if it's not, you uh render only the partial, only the part that will be swapped. So this is very important. And uh of course we are downloading the whole page, so let's see how the base template is uh is uh uh structured in the head we will uh download all the leaflet

10:47

Speaker 2: uh uh the leaflet stuff uh the the uh um so the m basically we will download uh the the um the um all the package that lets us work with the with a map And in the body we will include the the hypermedia partial, the single part that will be swept. effectively. Then we have another division with uh the which I call the the island and uh the this is where the uh the the the map will will be will be placed and we have to call um a script a custom script that manages the the the function functionality of the map

11:33

Speaker 2: and at the end we have to download HTMX because uh unless nothing works So uh let's see the hypermedia partial. Uh obviously it differs if it's a list view, if it's a detail view, update view and so on. But the structure is this. You load some template tags from uh Django GeoJSON. You will have some content, you will have uh the user interface, and there is a very important at the end There is this script which has an uh ID map data and uh it it uses uh uh

12:18

Speaker 2: GeoJSON uh template tag, the GeoJSO feature, and um It gets the objekt lists. This miss that dets all the locations and it transforms it into a geogasson structur. And it holds not only the geographic uh the geographic information, but also you see the pop-up content. This means that it holds also all the links that we we wrote before with the method, with the previous method into the into the model. location model. We have to see a little bit of

13:04

Speaker 2: JavaScript because it's important. We this is the the map script, this is the the the file that uh manages the uh the leaflet uh uh the leaflet map. And uh you see at the beginning uh there is uh the the map is uh initiated but this is the only time that we will do it just the first time. And then we call a base map with all the tiles , the tiles that form the the the map and it's important to have a a layer group where we will place all the all the markers because we want to be able to erase them

13:51

Speaker 2: in uh in uh uh other moments because we don't have we don't want to touch the map the the whole map but just erase uh some information and add some information. In fact you see that there is uh this get collections uh find that removes the objects from the the marker layer, then it goes and reads from the hypermedia part, reads all the GeoJSON information. and then it transforms it into the markers that we have on the map. And at the end uh it fits the bounds of all these markers and it zooms in and so you will see this.

14:37

Speaker 2: You will see all the markers and of course the markers were generated automatically so they cover up all the surface of the globe. But we can zoom a little bit in and for example we can click on one of these markers and the pop-up will come forward and clicking on on Capri we should go to the detail view of our application But uh of course if uh I have to be uh careful because if I leave the If I leave the link like I I've shown you before in the in the pop-up

15:22

Speaker 2: content method , it would happen that uh all the whole page would be reloaded. And of course we don't want this. So I told you a lie before. It's not uh It's not written with the the hypertext reference with the your URL inside. The uh the the hypertext reference is uh null. And there will be an attribute with an on-click that calls a function, open location, which has an argument with the URL. And in uh if we get back to the map script, we will see that this function has inside an HTMX Ajax

16:07

Speaker 2: call. So in this moment we are seeing HTMX from the inside under the hood because normally we don't use it this way HTMX makes an Ajax call, an asynchronous call with a get method to an IR uh URL. And at the end you see uh the the target of this uh of this request. So uh He's saying you get this you get uh this uh response and you place it into uh a piece of the DOM. Okay So we go to the

16:53

Speaker 2: location detail view. It's a generic detail view. and it has uh the the get template names as the list view that we have seen before but it uh tweaks also the dispatch method this is very important And uh this method says if the request is made from HTMX, you have to add this header to the response. And the the response adds this header which comes of which is uh uh a custom HTMX uh uh header which triggers uh an event uh after the swap you see HTMX

17:39

Speaker 2: trigger after the swap that that means that after that uh after the the piece of HTML is uh swapped you have to trigger that uh uh that event and what happens Just there is a in MapScript there is an event listener that refreshes all the data. So it erases back everything that is on the map and reads again into the new Abermedia part of the of the DOM uh reads uh the GeoJSON data and uh puts the the the new the new markers on the map fits the bounds and and zooms So what you will see is this

18:25

Speaker 2: this: you will see the detail view. So we have zoomed into Capri and now we are uh near the funicolare the funicolare station. Which is uh I don't know if you've been there. And you see we have uh some content and we have some uh user interface, but uh we see that We would like the marker to be a little bit displaced over the south because the relevant part here is the piazzetta and not funicolare station. So uh we want to update this. Um okay uh normally when we uh use

19:10

Speaker 2: maps and we want to create or update. Normally we we need a widget and normally we will we will load uh another library like uh Django Leaflet uh which uh has these uh uh the build built-in uh widgets so that we can have um map widgets on our front end. But we don't we don't want that because if we do that we will have to reload everything back. We want to use the same map. The same map that we are using for seeing the list view, the detail view. Okay, so we click on update location.

19:56

Speaker 2: This is a real HTMX uh request. So we have uh attributes. We will see that later in in another talk. What happens? Okay, we are doing an we are reaching an update view. We of of course we have a form. In this form we will have uh some new uh fields, latitude and longitude, because it's a little bit tricky to use A JSON inside a form. So I don't call the the germ field. You see in the klass mate, I don't call the germ field. I make these two

20:41

Speaker 2: fields. I can validate them if they are not correct because latitude can't be more than 90 degrees or less than minus 90 and so on. Into the update view uh we will have a get initial which uh uh gets the latitude and longitude initials from the geographic field which is in the database. And when the all the process ends with format valid, we will do exactly the opposite and we will fill the geographic field with the lat and long clean data. So

21:27

Speaker 2: there is another thing that I add to the location update view into the context data. I put an um the map status and we see we will see why uh it's uh it it's rendered in the location update it's render uh HTML in the template it's rendered as as a GeoJSON. This JSON script uh template tag is built in in uh in a Django. And so what happens here we are we have the here we have the the update view uh So you see on the on the right we have the the the form and we can change the title we can change the

22:14

Speaker 2: the description and uh We could also manually change latitude and longitude, but of course that would be a little bit a mess. But if we click on the map What happens? Let's say that we move, we don't want the marker to be on the on the red cross, but we want it to be on the piazzetta. So we just click on the piazzetta and the fields will be automatically updated and the marker will be placed where we have clicked. And this using without using special widgets, we are just using the previous map,

23:01

Speaker 2: which has never changed. in its uh uh in its it has never been uh reiniti initi initiated uh excuse me. And uh uh this uh You see that on the bottom you have a map on click. uh function. This is built in in left in Leaflet and it fires uh uh an event And what uh the update lat longer event uh it does what what does it do? It reads the map status on the on the HTML and it see it looks for the uh map

23:48

Speaker 2: on click uh uh key. And if it's true it goes on because we want this clicking on the map to work only if we want to update or create a new location and not just uh uh make it fire when when we are uh looking at uh detail view or uh or list view. So when if the map status map on click is true, we uh we update the the Latin long fields and we delete the the objects from the marker layer and we put the next the the the updated position uh with uh using the event

24:33

Speaker 2: uh geographic coordinates. So I uh I finish uh my my talk I hope I I I've been uh uh you've uh appreciated it and uh that's all

25:03

Speaker 1: Thank you so much. Can I ask you uh what the um again what was the project for? Um

25:13

Speaker 2: no I I've done uh uh other the the other project, no I or this one No, this one is is just to show how to use uh a map without uh fancy stuff, without uh uh having too much libraries. Just uh it's it's just uh proof of concept. Uh yeah, that's uh that's all it's just to show that you can do this without having too much stuff around. Okay. That's all. Because I I've used PostGIS, I've used Giorgiango in other projects when you have uh you need more complexity. In example If you don't have to just click on a map and put a marker on a map, but

26:00

Speaker 2: if you have to draw a polygon on a map This couldn't be possible or maybe it could be possible but but very complicated. So I would just download Django Leaflet and take his uh widgets and use them here. But if you do so you need some libraries, other libraries. So it it gets uh uh it it um It uh swells in some way.

26:28

Speaker 1: Yeah. Thank you so much. There is time for questions. It was really nice to see uh code. I felt I felt the itch. Yeah, yeah. I don't know the keyboard starting to click out there too. You can't show developers too much

26:49

Speaker 2: But you can you can see the the the whole uh code on on in that uh over there on GitHub over there. So Okay. No questions, but maybe it's better. No we can go we can go onward.

27:07

Speaker 1: There is a pop quiz afterwards and it's important with these details, by the way.

27:18

Speaker 3: I'll just sneak in one again. I do I'm sort of lost in how do you go from being an architect and like actually architect and buildings, how do you end up doing this?

27:30

Speaker 2: No look uh actually in uh architecture w they are trying to uh be a little bit more uh into programming because uh now there is all this uh hype of uh building uh information management. No, you want to a building you want to be it like a database You you know there is a carpet. This carpet is here and it's made uh from wool and it's uh the dimensions are this because maybe you have twenty carpets in uh uh in a whole building and so uh you need to track them. No, where are the carpets? Uh how they've been uh rolled

28:16

Speaker 2: and things like that. So they're starting to make it uh a little bit more uh uh programmable and of course there is also uh 20 years ago they started making all this flamboyant architecture with uh uh very complex curves and and things like that. And that was made possible just because there were programs that uh enabled that. And uh so you have parametric the design stuff like that. But in the end, if you just see Autogad and how it is structured, it's heavily

29:03

Speaker 2: programmatic. And people don't use it like that. People just use it to draw lines. But that's not uh that's not uh the the real uh um intention of the of uh Autogut. In Autogat you need to have the information that's important So for me it was natural. I was already inside a little bit of programming. I've done with basic I've done I've done structural analysis. and things like that. It's very easy. You just have to you have a matrix and you have to invert it. That's all. And but you can do very complex things with uh with just uh uh little uh

29:48

Speaker 2: little knowledge in the end. And another thing that I like is when you connect different things like from Autogad take uh the informations and uh and uh pour it into uh another uh la language another uh system and the uh the the way back of course. That's uh I I find that very interesting.

30:18

Speaker 1: I have a question about um this this example project it's it's very nice to uh to use to understand how um

30:29

Speaker 2: yes

30:29

Speaker 1: how the basics work uh if you do more uh complex have have you can you avoid having a whole node uh js stack in place when you're working with with maps or

30:44

Speaker 2: uh yes yes

30:45

Speaker 1: a lot of javascript no no this is not can you keep uh

30:48

Speaker 2: no no it's very th this uh is it's all very basic. You you need sqlite You don't you don't need strange backends, you don't need you don't need strange things. But this is done on purpose, on purpose, of course to take it uh to have it as simple as possible.

31:07

Speaker 1: Yeah. But even when you big lar when you've built larger projects you have achieved to keep it

31:14

Speaker 2: Always. Of course not always. But uh it's the first thing you you think. I I want to keep it simple. to manage in the end. So I I do the all this for fun. So I don't want to be bothered with uh with strange things uh uh that I I can't grasp no?

31:43

Speaker 1: Yeah. Yeah, keep it fun.

31:45

Speaker 2: Okay.

31:47

Speaker 1: Are there more uh questions? Otherwise we have uh the next talk coming up in two minutes. No, wait, no. Break coming up in two minutes. Sorry. Yeah, but let's give a big round of applause for Andrea.

32:03

Speaker 2: Thank you. Thank you very much

Questions this talk answers

Can you make a simple Django map without PostGIS or Django Leaflet?

Yes. This proof of concept uses Django, Leaflet, HTMX, and Django GeoJSON, which can serialize locations without PostGIS, PostgreSQL, or GDAL; for more complex drawing tasks such as polygons, the speaker recommends using Django Leaflet widgets instead.

Discussed at 7:43

How do you build a Django map with HTMX without reloading the whole page?

Render the full page on a normal request, but return only the hypermedia fragment for HTMX requests. HTMX swaps that fragment into the page while a separate Leaflet map remains in place.

Discussed at 10:01

How can a Leaflet map keep working as Django pages change through HTMX?

Keep the map initialized as a separate interactive island, and put the map’s GeoJSON data in the swappable page fragment. After an HTMX swap, listen for the swap event, clear the marker layer, and repopulate it from the new fragment’s GeoJSON.

Discussed at 13:04

How can users update a location by clicking an existing map in Django?

Include latitude and longitude fields in the update form and enable map-click handling only in create or update mode. When the user clicks, copy the clicked coordinates into the fields and move the marker without replacing the map.

Discussed at 22:14

Presenters

Note: We understand that names change, people change, and bodies change. We respect each individual's journey and privacy. If you have any concerns about a video or need us to remove content, please don't hesitate to contact us. We will handle your request with care and promptly address any issues.

More videos from Django Day Copenhagen