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 erikjamesmason

erikjamesmason on May 8, 2019

Thanks for the tutorial! It definitely piqued my interest!

Avatar image for bultita

bultita on May 10, 2019

Thanks! It is to the point and most of the explanations are great. However, * I expected more based on the topic and did not get all what I expected personally, I would love to have more interactive map with additional functionalities not just static map at the end of the course.

  • the course can be improved by:
  • Explaining the concepts in detail, as it was not detail enough particularly when it comes to the views
  • Add more on the mapping aspect, I think most people will take this course if you focus and strengthen the GIS part. There are lots of course on Django and what is missing is the link with GIS which you did elegantly but lacks depth.

Thanks and happy to come back and check when you have more courses on this.

Avatar image for Jackie Wilson

Jackie Wilson RP Team on May 10, 2019

Thanks for your feedback and suggestions. While it was a conscious decision to keep the course short (which abbreviated the GIS and Leaflet parts), maybe this is an opportunity for a multi-part series?

Avatar image for bultita

bultita on May 10, 2019

Thanks for your response. I agree, to keep course shorter and to the point it right. Please add new courses as series.

Avatar image for bultita

bultita on May 10, 2019

Thanks for your response. I agree, to keep course shorter and to the point it great. Please add new courses as series.

Avatar image for erikjamesmason

erikjamesmason on May 11, 2019

I second the multi-series. I work with GIS systems and would love to have an alternative resource for making interactive maps for public-facing data.

Avatar image for Jackie Wilson

Jackie Wilson RP Team on May 13, 2019

If we expanded the series, what platforms would you like covered? Do you think open source, like a QGIS, OpenStreetMap, Google Maps / Leaflet? Or Mapbox? Esri? The RP courses tend to be shorter and to the point, so it might be individual articles and videos arranged as a collection.

Avatar image for Kevin M

Kevin M on May 14, 2019

This tutorial was awesome . I’m developing a platform for an IoT project about remote monitoring. It would be great incorporating google maps or Mapbox, as well as how to display alerts or something when a parameter is being sent from a remote device. I’ll wait for any resource.

Thank you!!!

Avatar image for Jackie Wilson

Jackie Wilson RP Team on May 15, 2019

Kevin M, thanks for the feedback! Your project sounds really interesting. Do you plan to use Postgres for the data?

Avatar image for Kevin M

Kevin M on May 15, 2019

I’m evaluating different options. The main idea is to develop my own platform as well as my own servers. I’m actually considering to connect the devices (raspberry, etc) to a Postgres database. So, all connected devices must be displayed in the platform (a map where all locations are shown). However, when a button is pressed the raspberry (or any other microcontroller) should send a parameter (1 or 0) and the map must show an alert with all info of the place where that alert is being sent.

The easiest way is to simply use an IoT cloud and configure a simple map in a Dashboard for that cloud. But I’m actually trying is to set up everything from scratch. So, I’m trying to connect a device to Postgres and store the parameter and load that data in the platform. Yes, all devices will be around the city and must be monitor form a central place.

Any resources you could share would be wonderful.

(I’m good at doing Data Science and sensors/devices programming with Python. But trying to get better at building web platforms for Internet of Thing Projects)

Avatar image for erikjamesmason

erikjamesmason on May 16, 2019

I predominately work with ESRI and the ArcGIS appsuite, so I would be curious to see some of the geoprocessing functions from a different set of eyes. Or how to make webapps with my already defined maps from ArcGIS Online. Now that would be a fantastic tutorial (for me…)

Avatar image for Hizakakkun

Hizakakkun on June 4, 2019

Similar to bultita, I could have used a little more detail. Overall this course was good and I learned a lot. Thank you!

Avatar image for bultita

bultita on June 13, 2019

I think it is better to keep using the open source software you have used plus add mapbox if possible. Django - plotly dash integration would also be a great addition as there is no such course out there but it can help to link django with dash - dashboard and it has a GIS capabilities.

Avatar image for Abby Jones

Abby Jones on Aug. 4, 2019

This is so awesome!!!!!!!!!!!!!!!!!!

Avatar image for eclaudio

eclaudio on Feb. 11, 2020

Thank you so much for this tutorial. I attempted to deploy this project as part of my portfolio project. My issue is connecting the project to a hosted Database. I could not find an excellent place to host the DB with considerations to PostGIS. I would love a recommendation as to where to host the data so that I could get this up and running, and again thank you.

Avatar image for Jackie Wilson

Jackie Wilson RP Team on Feb. 13, 2020

Hi @eclaudio, this is not to endorse any product over another, but I have not had any issues hosting PostGreSQL/PostGIS on AWS. I don’t think it makes a difference where, as long as when you go to install the PostGIS extensions using the PostGres admin tool, just point to the remote resource address (vs a local db resource name). You mention “portfolio”, so if you are a student, AWS offers a free tier with some added features for education customers. Even without those education extras, the free tier should allow you to install the PostGIS extensions without incurring any costs. There might be a trial time or usage, but it should be fine to try out your code in the short term. Hope that helps.

Avatar image for dthomas01

dthomas01 on March 18, 2020

Hello Jackie, Wow…I’m really impressed. Being fairly new with Python, Django, Postgres and total newbie in GIS, this really helped to understand how the pieces fit together a lot better. I was impressed that the final map was indeed interactive. I clicked/held mouse down in the middle and panned the map left and right. Zooming in did give lots more detail. Certainly appreciate the detail on using Django and how you loaded the data. You really packed a lot of information into a single course!

I’m now wondering if there is a way to show mouse hover text over the marker points that give more detail on the locations found. That way, the address doesn’t take up valuable screen space especially for smaller form factor browser devices. Perhaps for a Part 2, you could show that “Geo coding” concept where a user keys in their own city/state -or- zipcode and using a centerpoint maybe…find nearest locations....using Python 3.7?

Appreciate ya! Dave

Avatar image for Philip Waku

Philip Waku on March 26, 2020

Hello Jackie, Thank you so much for putting this tutorial together; i enjoyed every bit of it and learned some new stuff.. I’m always new to the POSTGIS feature on postgres and you made it look so easy and fun to follow and implement. With the current situation here in Italy, I’m thinking of making a location web-based Covid-19 application that tells us in real time how many free spaces there are in the different departments of all Italian Covid-19 hospitals and within the same same project an app where it is possible to load the availability of housing to accommodate healthcare personnel who must move quickly from a certain region to a certain hospital to help people who are sick. I would appreciate if you could kindly up the series with more details on the already used tools. Thank you once again. Philip

Avatar image for Mydhe

Mydhe on April 4, 2020

Great Tutorial Jackie. Another series would be even better to have more interactive maps and features than a static map at the end exhausting GIS applicability with Django/PostgreSQl

Thank you.

Avatar image for Stazy

Stazy on April 5, 2020

I am playing around with the code and trying to set markers for each shop and include a popup with the shop’s name. This is the code I’m working with and it’s not working:

    {% for shop in shops %}
    var mark = L.marker([{{ shop.location.y }}, {{ shop.location.x  }}], {
    }).addTo(map)
    .bindPopup(shop.name);
    {% endfor %}

Any suggestions?

Avatar image for Ricky White

Ricky White RP Team on April 6, 2020

Is that Javascript you are using in between the python template tags? If so you should have it in a script tag in your html file.

@Stazy You need to put shop.name inside handlebars {{ ... }}, like you’ve done with shop.location.y so it is treated as a django template variable. And inside quotes "" to make it a string.

{% for shop in shops %}
var mark = L.marker([{{ shop.location.y }}, {{ shop.location.x  }}], {
}).addTo(map)
.bindPopup("{{ shop.name }}");
{% endfor %}
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?

Become a Member to join the conversation.