Part 4: Creating a location-based app for Heroku in Termux on Android

Summary

CacteGra
4 min readOct 14, 2019

In the last few parts of our tutorial series, we have been developing a Django web application on Android using Termux, deploying it to Heroku. However it is here that we will be limited in our development on Android as geospatial database package is not supported on Termux as of yet; this will only hinder our ability to run the app locally as we can still create the app and deploy it on Heroku.

Here we are going to make a simple location app that will display the user’s position on a map on our website. The project is available now on Github.

Adding Linux packages necessary for a geospatial database:

heroku buildpacks:set https://github.com/cyberdelia/heroku-geo-buildpack.git

We then add the PostGIS extension to our Postgresql database (see part 3 for our postgres database tutorial):

heroku pg:psql
create extension postgis;

Quit by typing:

\q

This extension is especially to make postgresql work better with spatial data.

Edit name_of_app/settings.py to add geodjango to installed apps:

INSTALLED_APPS = [

‘django.contrib.gis’,
]
And at the end of the same file add:
GDAL_LIBRARY_PATH = os.environ.get(‘GDAL_LIBRARY_PATH’)
GEOS_LIBRARY_PATH = os.environ.get(‘GEOS_LIBRARY_PATH’)

Login to Heroku and set Heroku to use the geospatial libraries from the default python buildpack:

heroku config:set BUILD_WITH_GEO_LIBRARIES=1

The necessary Gdal library is not available in Termux, so we can’t install Gdal using pip. Before starting a new app inside Django, we need to comment the geodjango line in settings.py:

INSTALLED_APPS = [

# ‘django.contrib.gis’,
]

Then start a new application with:

python manage.py startapp name_of_application

Add the app and uncomment the following line in settings:

INSTALLED_APPS = [

‘django.contrib.gis’,
‘name_of_application’,
]

Edit the __init__.py in the name_of_application folder, it should reflect what is inside the name_of_application/apps.py file:

default_app_config= “name_of_application.apps.Name_Of_ApplicationConfig”

Specify the template directory in settings, where Django will look for html files:

TEMPLATES = [
{
‘BACKEND’: ‘django.template.backends.django.DjangoTemplates’,
‘DIRS’: [os.path.join(BASE_DIR, ‘templates’)],

Let’s start with displaying a basic OpenStreetMap on the home page of our application.
First install Leaflet for Django. Leaflet is an open-source JavaScript library for displaying interactive maps. The Django module is an integration of Leaflet into the web framework for easier use.

pip install django-leaflet

Add the application to settings:

INSTALLED_APPS = [

‘leaflet’,
]

Edit name_of_application/views.py:

from django.shortcuts import render# Create your views here.
from django.http import HttpResponse
from django.core.serializers import serialize
from django.views.generic import TemplateView
class MainPageView(TemplateView):
template_name = ‘name_of_application/home.html’

Now we need to tell Django which url will link the view and the template. We are going to use a urls.py file inside name_of_application to store all of the urls related to the application so that the code is clearer. Edit name_of_app/urls.py and add the following:

urlpatterns = [

url(‘’, include(‘name_of_application.urls’)),
]

Now create the name_of_applicstaticurls.py file in which we specify the home page URL to load the view created earlier:

“””digitalquint URL ConfigurationThe `urlpatterns` list routes URLs to views. For more information please see:
https://docs.djangoproject.com/en/2.2/topics/http/urls/
Examples:
Function views
1. Add an import: from my_app import views
2. Add a URL to urlpatterns: path(‘’, views.home, name=’home’)
Class-based views
1. Add an import: from other_app.views import Home
2. Add a URL to urlpatterns: path(‘’, Home.as_view(), name=’home’)
Including another URLconf
1. Import the include() function: from django.urls import include, path
2. Add a URL to urlpatterns: path(‘blog/’, include(‘blog.urls’))
“””
from django.conf.urls import url
from django.urls import path
from django.conf import settings
from django.conf.urls.static import static
from name_of_application.views import MainPageViewurlpatterns = [
url(r’^$’, MainPageView.as_view()),
]

Now to create the folder structure for the template. First in the app root folder (with manage.py) create:

mkdir templates
cd templates
mkdir name_of_application
cd name_of_application
nano home.html
<html>
{% load leaflet_tags %}
{% load static %}
<head>
<meta name=”viewport” content=”width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no” />
<style media=”screen”>
#local { width:100%; height:100% }
</style>
{% leaflet_js %}
{% leaflet_css %}
<link rel=”stylesheet” href=”Leaflet.markercluster/dist/MarkerCluster.css” />
<link rel=”stylesheet” href=”Leaflet.markercluster/dist/MarkerCluster.Default.css”/>
<script>
function mapInit(map, options) {
L.tileLayer(‘https://api.tiles.mapbox.com/v4/mapbox.streets/{z}/{x}/{y}.png?access_token={{ mapbox_key }}’, {
attribution: ‘<a href=”http://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>, Imagery © <a href=”http://mapbox.com">Mapbox</a>',
}).addTo(map);
map.locate({setView: true, maxZoom: 15});
function onLocationFound(e) {
var radius = e.accuracy;
L.marker(e.latlng).addTo(map)
.bindPopup(“You are within “ + radius + “ meters from this point”).openPopup();
L.circle(e.latlng, radius).addTo(map);
}
map.on(‘locationfound’, onLocationFound);
function onLocationError(e) {
alert(e.message); }
map.on(‘locationerror’, onLocationError);
};</script>
</head>
<body>
{% leaflet_map “map” callback=”mapInit” %}
</body>
</html>

Nowadays, web browsers require a website to use SSL encryption, https in order to let the user allow sharing his location. Fortunately, any Heroku app can be accessed using the SSL certificate. Just put https in the URL to your app and you will be able to share your location with the app:
https://name_of_app.herokuapp.com

--

--

CacteGra

It's all about interweaving words and code to create something new.