Create the "nearbyshops" View
Nearly everything for the backend of our application is complete. In this video we’ll concentrate on the frontend in order to give our user a way to see the shops near their location.
What we’ll do in this video is create a Django view in our nearbyshops app and then route users to that view through the main urls.py.
It might help to revisit what happens with an incoming request, which we covered in video #6.
Downloadable Sample Project: This course includes a downloadable sample project that demonstrates the final state of the Django app you’ll build throughout the course. You can get the source code for it here on the materials
repo.
00:00 Welcome to video number ten in our series on making a location-based web app with Django and GeoDjango. Nearly everything for the backend of our application is complete. In this video, we’ll concentrate on the frontend, in order to give our user a way to see the shops near their location.
00:18
What we’ll do in this video is create a Django view in our nearbyshops
app, and then route users to that view through the main urls.py
.
00:27
It might help to revisit what happens with an incoming request, which we covered in video number six. Our Django project is called shops
. It was created by the startproject
script, so it includes the starter files settings.py
and urls.py
.
00:42
It acts as the main gate to our website. Our Django app is nearbyshops
, a component of the shops
project. nearbyshops
was created as an app by the startapp
script. This created a folder of the same name, which included starter files for building responses to incoming requests.
01:01
One of these starter files is views.py
. views.py
works together with an HTML template file to create a webpage to send back to the user to display in their browser.
01:14
You’ll do the following three things to make all of this work: You’ll create a view in views.py
. views.py
is already there, we just have to fill in some missing code. You’ll create an HTML template.
01:26
The template is not there, so we’re going to have to build that from scratch. And then finally, we’ll add a route to the view in urls.py
. So let’s get started with that views.py
file and create a view. views.py
is located in your app folder—in this case, the nearbyshops/
folder.
01:45
Let’s take a look at what’s inside views.py
. Since our app is new, the file is empty except for a small amount of starter code. But typically in a Django app, you’d find functions and classes here that would correspond to various routes and responses.
01:59 We will create one of these to formulate a response coming in through the homepage of our site or the landing page when a browser loads the root of our site.
02:09 You’ve heard me say before that Django is a batteries included framework. One of the batteries that Django provides is generic views. Some webpage views are so common, Django provides classes for them.
02:21
One of these classes is ListView
, which provides a basic list view display of items returned from a query. We will subclass this and customize it for our use.
02:34
Return to views.py
. Leave the existing import
statement there, but create the following four lines of code to import additional requirements.
02:43
Pause the video here if needed. Next, create two variables, latitude
and longitude
. We are going to use these values to simulate our user being somewhere in the city of Baltimore.
02:57
Then, to turn these coordinates into a geographic map point that GeoDjango can understand, add the next line of code. The srid
value is a common type of spatial reference system.
03:11
It’s now time to subclass ListView
. The following code will complete this task for us. Notice the last line in our class. This is the path where our view will look for its companion template.
03:25
Pause the video if needed, and duplicate this code. Before we create our template, let’s go back and visit one of the project files, settings.py
.
03:34
The way Django works with templates is determined by the settings in the TEMPLATES
variable. Yours should still have the defaults. I want to explain two of these settings.
03:45
The first entry, 'BACKEND'
, tells us what template language Django will use. In this case, the default is the Django template language, or DTL. Newer versions of Django can use others such as Jinja.
03:57
The second setting I want to explain is the 'APP_DIRS'
setting that’s set to Boolean True
. With this setting True
, Django will expect to find templates inside of the app folder—in our case, nearbyshops/
. Not only that, it will expect to find the templates in a specific directory named templates
.
04:17
Therefore, we will need to create the templates/
folder first, within our nearbyshops
app.
04:27
We have one more consideration before creating our template file, and that is when we subclass ListView
, we specify this path to our template.
04:35
This is a relative path, and because our 'APP_DIRS'
setting is True
, that means this is the path we use once we are within the templates/
folder.
04:45
So we have an additional subfolder to create called shops
.
04:53 Now, our path is correct. Templates are just HTML files that include special template syntax mixed in. This syntax is often referred to as handlebar or mustache syntax, and its job is to format dynamic data into your page.
05:10
This is the template we will create now, as the file index.html
within the shops/
subfolder.
05:29
Your last task in this video is to add your routes. This is handled by the project side in urls.py
. Let’s create it now. For urls.py
to reference anything in views.py
it needs access, so import views
as a module by way of nearbyshops
, like this.
05:49
Finally, add your route to urlpatterns
by using the path()
method. The arguments will be your site route as a string, followed by the view that should respond. Our path is the root, so it’s an empty string, and the response will be our Home
class.
06:12 Let’s launch the site and see if our changes worked.
06:20 And here we go! Here’s the closest shops nearest to our pretend user. Great job. Thanks for sticking with me so far. If you can handle just one more video, I’ll show you how to make this page prettier with Leaflet.
Abby Jones on Aug. 4, 2019
Okay fixed that part (was missing .gis. in the Distance import. Now, it returns a blank html page. I think I can figure this one out lol.
Abby Jones on Aug. 4, 2019
Was missing a “
grumbles
dthomas01 on March 18, 2020
Hi folks, Got a question about the RP tutorial for GeoDjango Nearby Shops. Wondered if anyone could point me in the right direction on switching units of measure. I’d be very grateful for any help.
Saw that nearest 6 shops displays as ‘meters’ with lots of decimal places. Tried converting output to be ‘miles’ instead…but not sure where in code or configuration to make that switch. (Agree that meter units are more precise than miles for the comparison to determine which shops indeed are nearest. Just wanted the output listing converted to miles, if possible. Not seeing how..because though value can be changed, the units still persist showing meters.)
Original code shows meters:
queryset = Shop.objects.annotate(distance=Distance("location", user_location)).order_by("distance")[0:6]
Webpage showed:
Cleaners Lobby Shop: 96.98014712 m
Introduce division…but units were unchanged:
queryset = Shop.objects.annotate(distance=Distance("location", user_location)/1609.344).order_by("distance")[0:6]
Webpage still showed units symbol ‘m’:
Cleaners Lobby Shop: 0.060260669639306444 m
Maybe this is a GeoDjango config or such? Baffled....
Thanks, Dave
dthomas01 on March 19, 2020
Follow up to prior post… I solve the index.html shop.distance conversion from meters to miles myself…but not the rounding to limit how many decimal places. Passing this along for others.
Instead of using {{ shop.name }} : {{ shop.distance }} I switched to {{ shop.name }} : {{ shop.distance.mi }} mi
dthomas01 on March 19, 2020
Hello all, Okay I just now solved the decimal rounding issue too. Passing this along. So to get the distance both converted to miles and decimal rounding too, I’m using the following in the index.html file:
{{ shop.name }} ( {{ shop.distance.mi|floatformat:2 }} mi )
Dave
ankitzin on June 16, 2020
can we show these value in maps that would be great. Please give me so idea about that
taylorchris121 on June 7, 2021
Hi Jackie,
Lovin the course and so far ive switched from windows to mac but getting this error
Error during template rendering
In template /Users/christaylor/geoshops/nearbyshops/templates/shops/index.html, error at line 25
function st_distancesphere(character varying, geometry) does not exist LINE 1: ...shops_shop"."address", "nearbyshops_shop"."city", ST_Distanc... ^ HINT: No function matches the given name and argument types. You might need to add explicit type casts.
15 crossorigin=""></script>
16
17 <!-- Set map height -->
18 <style>
19 #mapid { height: 500px; }
20 </style>
21 </head>
22 <body>
23
24 <h1>Nearby Shops</h1>
25 {% if shops %}
26 <ul>
27 {% for shop in shops %}
28 <li>
29 {{ shop.name }}: {{shop.distance}}
30 </li>
31 {% endfor %}
32 </ul>
33 {% endif %}
34
35 <!-- map div -->
taylorchris121 on June 7, 2021
To clarify
25 {% if shops %}
Error during template rendering
In template /Users/christaylor/geoshops/nearbyshops/templates/shops/index.html, error at line 25
Become a Member to join the conversation.
Abby Jones on Aug. 4, 2019
Hmmm, everything was going great when I left my code running last night. I logged in this morning and now I have a ton of errors in the libraries. It is also having trouble importing Distance from django.contrib.db.models.functions