Locked learning resources

Join us and get access to thousands of tutorials and a community of expert Pythonistas.

Unlock This Lesson

Locked learning resources

This lesson is for members only. Join us and get access to thousands of tutorials and a community of expert Pythonistas.

Unlock This Lesson

Bonus Video: Intro to Leaflet

Welcome to the 11th and final video of this series where, if you made it this far, you’ve succeeded in Making a Location-Based Web Application with Django and GeoDjango. Congratulations!

This video is a bonus video to show you how to incorporate maps into your site for a better user experience.

To accomplish this task you’ll learn about Leaflet, a popular, lightweight open source library that makes it easy to build interactive maps.

00:00 Welcome to the eleventh and final video of this series, where—if you made it this far—you’ve succeeded in making a location-based web application with Django and GeoDjango. Congratulations!

00:11 This video is a bonus video to show you how to incorporate maps into your site for a better user experience. To accomplish this task, you’ll learn about Leaflet, a popular, lightweight open-source library that makes it easy to build interactive maps.

00:25 This is your website after completing the video series so far. It accomplishes what we set out to do, but it could be better. This is where Leaflet comes in.

00:36 Leaflet is a JavaScript library that’s simple to work with. You can find them on the web at leafletjs.com. If you’re new to Leaflet, the easiest way to get started on your own is to follow their Quick Start Guide at this address. But we are going to set up Leaflet right now in this video.

00:55 To add Leaflet to your nearbyshops page, you’ll need to add five pieces of code to your index.html template. To your <head> section, you’ll add three things: a CSS link to leaflet.css, a script link to leaflet.js, and then a short piece of CSS to set a map height for a map ID. In the <body> section, you’ll add two things: an empty <div> with the ID you used in your CSS above, and then at the bottom of your <body> section between <script> tags, you’ll add JavaScript to instantiate a map using OpenStreetMap tiles.

01:34 The best way to get the code snippets for the <head> section is to visit the Quick Start Guide and copy them, so let’s go there now. First, we will copy the CSS link, followed by the script link.

01:48 Then we will create the CSS to set the map height. In their example, they use the ID mapid. You can make the ID anything you like, you’ll just need to be consistent. Return to your editor.

02:01 If your site is running, stop it with Control + C. Open the index.html template located in nearbyshops/templates/shops/. We’ll modify this file to place our code in the following places.

02:15 It’s also important to have the code entered in this order, with the CSS referenced first.

02:22 Now, paste in the code snippets that you copied in their respective positions. The first two blocks of code can be pasted as is with no changes. However, you’ll need to create <style> tags before pasting in the CSS for the map height.

02:40 Next, scroll down to add the necessary pieces to the <body> section of your page. Add an empty <div> with your map ID.

02:50 The next section of code you’ll add is a little bit more involved and will require some minor modification. If you continue with the Quick Start page, you’ll see that their JavaScript to create the map uses Mapbox tiles.

03:02 Mapbox is a great product, and I highly recommend you check it out and sign up. But if you use this code, you’ll need to have an API key. In the interest of time, we’re going to create our map with OpenStreetMap tiles instead.

03:17 Luckily, there’s a code snippet for this ready to go on the homepage of Leaflet. We’ll just have to change a few things to get it to work. Back in the editor, I have index.html ready to edit, and I also have views.py on standby because I’ll need to borrow the lat/long coordinates we assigned earlier. At the end of the <body> section in the area we’ve specified, create <script> tags and paste the JavaScript you copied between them.

03:44 Then change the following items: The map ID, since it’s different from the one in the <div> we created. Then, let’s steal our lat/long coordinates from views.py so our map displays Baltimore.

04:01 We’ll use our lat/long to modify the first array argument in the .setView() method.

04:08 Then, we’ll take those same coordinates and we’ll change the array in the .marker() method. After that, let’s modify our popup message—just because.

04:24 Now it’s time to see the effects of the changes you’ve made so far. Launch your site and check it out.

04:34 Hm. Our map could be taller and optimally we’d like to see those locations as markers on the map. Let’s make that happen.

04:43 You’ll want to revisit Leaflet’s Quick Start Guide to find the code to create a marker. It’s a bit farther down the page in the Markers, circles and polygons section.

04:52 Here we see the codes to instantiate a Leaflet circle with various settings, and then immediately invoke its .addTo(map) method. Let’s copy this.

05:01 Let’s paste this code below our other map code in index.html. A Leaflet circle is a marker that will be added to our map, and we want to do this for each location that was returned from our query.

05:13 We already used template syntax to iterate through this QuerySet to form our list view. Why not use the same syntax in our JavaScript? Except that as we go, we’ll need to pull out the lat/long coordinates.

05:25 Here’s the code we pasted to create the markers. The first thing we should do is fix this so the variable name passed to the .addTo() method matches our map variable name, which is map. Next, we’ll add the template code to cycle through our shops.

05:40 This is on the same page as our list view, so the for loop we use for that will work just the same here, even using the same shops variable. With this loop, however, as the iterating shop holds our current record, we need to somehow access the lat/long coordinates from the dataset in order to replace these values. And if you recall, when we modeled our field names, we only had four: name, location, address, and city. What do we do?

06:07 This is where GeoDjango and PostGIS come to our rescue. In our schema, location is a PointField, and therefore the coordinates are accessible as a child value. Back in our code, replace the first coordinate, latitude, with shop.location.y. Replace the second, longitude, with shop.location.x.

06:30 Make sure your handlebar syntax is correct. Three more changes will make this webpage look even better. Let’s increase the height of the map so it fills more of the page.

06:46 Next, let’s adjust the zoom level upwards so we see more detail.

06:53 Finally, let’s reduce the size of the marker from 500, which is huge, to 5. It’s time to stop and relaunch our site.

07:08 Look how much better this looks. There are your six query records displayed visually on a map.

07:15 Now that you’ve completed this video series, you may want to explore more features in Leaflet. You may also want to use a geocoding API to translate human-readable addresses into map coordinates. I sincerely thank you for watching this video series.

07:29 If you have any ideas on how to improve this segment, please share your feedback in the comments below. Thanks for watching, and best of luck on your future projects.

Avatar image for kplrm

kplrm on May 3, 2020

it would be awesome to expand this series with OpenStreetMap and Leaflet. Optional Mapbox, since there is a good free tier. I would love to see how a user could interact (with the map in the sense): * user can click on the map to store its position (i.e. for getting a delivery) * user can select a shop when clicking on a marker * shops can have a “delivery coverage” and users only select shops that delivers to his current location * delivery person gets route to follow (walking or by car)

Avatar image for mikesult

mikesult on Aug. 12, 2020

This was a great tutorial. I really enjoyed the connection of the many different parts in this application: Postgres, Django, GeoDjango, Leafletjs. Plus the data source of overpass-turbo.eu was interesting and a great learning experience for me. I echo the comments of others to encourage more tutorials along this line. Thank you.

Avatar image for kentongoldthorpe

kentongoldthorpe on Sept. 17, 2020

I ran into many problems setting up the virtual environment. I did a bunch of googleing to learn what a virtual environment is and how to change PATH variables, but then I discovered Anaconda. I was able to set up the virtual environment and complete the project using Anaconda. I think it was much easier while actually being more dynamic. I like QGIS, but they’ve changed their program downloads since you made this series, so you have to download the older QGIS editions for this process to work the way you have set up in the videos.

I really enjoied the series and learned a lot thank you!

ps one big issue with the venv that I ran into early on was using the command

“python venv myvenv”

and not

“python3 venv myvenv”

this is because in the video you display the former accross the screen, but then when you type in the video you use the latter. This took a long time for me to catch.

Avatar image for karakus

karakus on Sept. 19, 2020

Thank you, that did what it said on the tin in terms of establishing the fundamentals of creating a Location based app with Django. I certainly enjoyed the style, detail and pace of the course. I feel confident that I can move forward from here in an informed manner.

My #1 takeaway - being introduced to overpass-turbo.eu What a great resource for grabbing geospatial data for my future projects!

Avatar image for Yvonne Wilmot

Yvonne Wilmot on Sept. 19, 2020

Very pleased with myself for getting to the end and then the bonus of seeing an interactive map on the page :) Loved the way you explained the workings in some of the areas. Really helpful. Was hoping to see a bit more interaction with user input at the end but I guess that would make the course long - so maybe a part 2 for this would be nice.

Other thing I was wondering about is how you’d manage larger city files? I’m in Singapore so thought I’d download that but it warned me that it might be too big so I cancelled it. But how would you deal with that?

I had a couple of issues getting all the necessary components installed, especially the drivers - (for Windows). I even deleted everything and started again only to get the same error - then read comments from other students and found the answer. Best way to learn!

It would be nice to update this course with the latest versions available so the installation screens match and perhaps mention the different commands for different OS (where different).

Avatar image for kbee181756

kbee181756 on Nov. 16, 2020

Great project.

Avatar image for kbiplob

kbiplob on May 8, 2021

Thank you Jackie for this concious course. I echo with bultita’s third point. There are hundreds of tutorials in udemy or youtube for Django. But, it is difficult to find a good coures Django with GIS.

I think it would be very helpful to extend few more lectures on the models, how someone can enter longitutde, latitude data from Django admin, perhaps writing scripts to upload CSV/Json files with different sets of data.

Avatar image for JoeFred

JoeFred on Dec. 21, 2022

Thank you for the great tutorial! I encountered just one issue on the final Leaflet portion:

        {% for shop in shops %}
            var circle = L.circle([{{ shop.location.y }}, {{ shop.location.x }}], {
                color: 'red',
                fillColor: '#f03',
                fillOpacity: 0.5,
                radius: 5
            }).addTo(map);
        {% endfor %}

My editor is expecting a js expression before the first ‘%’. Any suggestions? I’ve nested this within the same script tags as the map.

Avatar image for Martin Breuss

Martin Breuss RP Team on Jan. 2, 2023

Hi @JoeFred is the code still working and is it just your editor complaining, or do you run into an error?

If it’s just an editor alert, then you can ignore it. It can be hard for an editor syntax highlighter (or linter) to figure out such nested languages. In this case it’ll have to understand HTML that contains Django templating language that contains JavaScript code, so that might just be too much for whatever plugin is trying to tackle it : )

If it’s not working as expected, can you describe in more detail what doesn’t work and what you see instead of the expected result?

Avatar image for Pepe

Pepe on March 27, 2025

VERY useful course!!!! Thank you! Is there any continuation on this topic??

Become a Member to join the conversation.