Setup and Deploy Geodjango App on Alibaba Cloud Part 2: Completing the App

By Erick Otenyo, Alibaba Cloud Tech Share Author. Tech Share is Alibaba Cloud’s incentive program to encourage the sharing of technical knowledge and best practices within the cloud community.

This tutorial is a continuation of the article Setup and Deploy Geodjango Application on Alibaba Cloud Part 1. In part 1, we were able to setup the environment and install the geospatial libraries needed to create Geospatial applications with GeoDjango. We were also able to start the coffee shops application and test it in development mode. In this tutorial, we will continue building the coffee shops application to incorporate geospatial functionalities.

Developing Our Application Locally

To keep track of our applications’s python packages, we will create a requirements.txt file that will have a list of all the required packages for our application and their respective version using the following command:

(geodjango) $ pip freeze > requirements.txt

Make sure your virtual environment is activated prior to running the above command.

To copy the folder from our Alibaba ECS instance, you will use the scp command line tool from your local computer. Type the following command on your local computer terminal:

scp -r user@your_server_ip:/coffeeshops /home/user/Desktop/

You will be prompted for your instance’s password after which you will have the project downloaded in the location you specified. In this case we will have a coffeeshops folder with our code on the Desktop.

Go ahead and set up your environment by installing all the requirements as in the previous tutorial so as to have everything working. Also don’t forget to create and activate Python 3 your virtual environment on your local development computer. Create the database, set the correct database settings in settings.py and test your application if it works.

Creating the Geographic Application Component

(geodjango) :~/home/user/Desktop/coffeeshops/$ djang-admin startapp geo

This will create a new django app called geo inside our coffeeshops directory. A django app describes a Python package that provides some set of features. Django apps may also be reused in various projects. The new directory will look like this:

geo/
__init__.py
admin.py
apps.py
migrations/
__init__.py
models.py
tests.py
views.py

Add the created app to settings.py under installed apps

INSTALLED_APPS = [
...
'django.contrib.gis',
'geo'
]

Creating a Coffee Shops Model

  • name — the name of the coffee shop
  • location — the geographic coordinates of the coffee shop

We will tell django of this structure of our data through the models.py file. A model in Django contains the essential fields and behaviors of the data we are storing. Each model will map to a database table. A geodjango model is a django model that inherits from the django.contrib.gis module and supports geometry fields. Our location field will be a geometry field, thus we will need to define a Geodjango model.

Open the geo/models.py file and remove everything from it, and write code like this :

geo/models.pyfrom django.contrib.gis.db import modelsclass CoffeeShop(models.Model):
name = models.CharField(max_length=50)
location = models.PointField(srid=4326)

# Returns the string representation of the model.
def __str__(self):
return self.name

Note that the location field is a GeoDjango specific geometry field. This field is not available in the normal Django model fields definition.

The following table shows the common geographic data types and how they are represented in Geodjango models fields

| Data Type | Field Type |
| — — — — — — — | — — — — — — — — — — — — — — — — — — — -|
| Points | PointField/MultiPointField |
| Lines | LineStringField/MultiLineStringField |
| Polygons | PolygonField/MultiPolygonField |

This means not only can you have point data in Geodjango, but also you can have lines for example roads and polygon data for example buildings.

After defining our model, we need to sync with the database. First we create a database migration:

(geodjango) $ python manage.py makemigrations

Then run the migration:

(geodjango) $ python manage.py migrate

Django will create the actual table in our database using the fields defined in our model.

Loading Data with Layer Mapping

The LayerMapping utility provides a way to map the contents of vector spatial data files (e.g. shapefiles/geojson) into GeoDjango models.

We are going to use this cafes.geojson file, which contains the cafes that sell coffee around the Nairobi area in Kenya. Github Gist provides us with a nice preview of the data.

Download the cafes.geojson file, create a folder called data and save the cafes.geojson file there.

To use layermapping, create a file called load.py inside the geo folder with the following content:

geo/load.pyimport os
from django.contrib.gis.utils import LayerMapping
from django.conf import settings
from .models import CoffeeShop
coffeeshop_mapping = {
'name':'name',
'location':'POINT'
}
coffeeshops_file = os.path.join(settings.BASE_DIR, 'data', 'cafes.geojson')def run(verbose=True):
lm = LayerMapping(CoffeeShop, coffeeshops_file, coffeeshop_mapping, transform=False)
lm.save(strict=True, verbose=verbose)

Each key in the coffeeshop_mapping dictionary corresponds to a field in the CoffeeShop model. The value is the name of the geojson property that data will be loaded from. The key location for the geometry field is POINT, the geometry type GeoDjango will import the field as. The transform keyword is set to False because the data does not need to be converted – it's already in WGS84 (SRID=4326).

To import the data, invoke the Django shell from your project’s root directory

(geodjango) $ python manage.py shell
>>> from geo import load
>>> load.run()

The data will be imported into the database.

Using GeoDjango, we can quckily visualize each coffeeshop on a map in the django admin interface. A specific class called OSMGeoAdmin extends the normal django admin class to display a map of the point under the location field.

Edit the geo/admin.py with the following content:

from django.contrib import admin
from django.contrib.gis.admin import OSMGeoAdmin
from .models import CoffeeShop
# Register your models here.
admin.site.register(CoffeeShop, OSMGeoAdmin)

Edit your settings.py under ALLOWED_HOSTS to enable your app run on localhost:

ALLOWED_HOSTS = ['your_server_ip','localhost']

To view the changes so far, run the following commands

(geodjango) $ python manage.py createsuperuser
(geodjango) $ python manage.py runserver

You can view you app at http://localhost:8000 and the admin page at http://localhost:8000/admin

On the Admin page after logging in, click on Coffee Shops under GEO to see the list of the coffeeshops

Click on one shop to view the details and map.

The location field will automaticall display a map showing a point of where the cafe is located.

You can also use tools provided at the right corner of the map edit the location.

Perfoming Geospatial Queries

Let us do a query to get the cafes that are 1 kilometer or less from a given point. We will run this sample query from the django shell. Usually, you will not run the queries from the shell, but use django views to manage the queries, and display the results to the user probably on a map. We will use the Django shell to see how typical geospatial queries work.

(geodjango) $ python manage.py shell
>>> from django.contrib.gis.geos import Point
>>> pnt = Point(36.8145,-1.2890)
>>> from geo.models import CoffeeShop
>>> from django.contrib.gis.measure import D
>>> CoffeeShop.objects.filter(location__distance_lte=(pnt,D(km=1)))[:5]

The above will give a Django QuerySet of 5 cafes that are 1 kilometer or less from a point with coordinates [36.8145,-1.2890].

The above query just returns the results as they are obtained from the database. What if you need to sort them by distance such that the nearest cafe is the first one in the result?

The following code will return the 5 cafes sorted by distance, so that the nearest one is the first one:

(geodjango) $ python manage.py shell
>>> from django.contrib.gis.geos import Point
>>> pnt = Point(36.8145,-1.2890)
>>> from geo.models import CoffeeShop
>>> from django.contrib.gis.db.models.functions import Distance
>>> CoffeeShop.objects.annotate(distance=Distance('location',pnt)).order_by('distance')[:5]

Django supports other distance lookups from example finding cafes that are more than 2 km away and other geospatial queries. We have barely just scratched the surface of what is possible with GeoDjango. For a complete reference, check out the GeoDjango Database API.

Updating the Project Folder on Alibaba Cloud ECS

scp -r /home/user/Desktop/coffeeshops user@your_server_ip:~/

Activate your virtual environment on the server:

workon geodjango

Run migrations:

(geodjango) user@server_ip:~/coffeeshops$ python manage.py migrate

Import coffee cafes to the server database:

(geodjango) user@server_ip:~/coffeeshops$ python manage.py shell
>>> from geo import load
>>> load.run()

Run development server:

(geodjango) user@server_ip:~/coffeeshops$ python manage.py runserver 0.0.0.0:8000

You should be able to view the application on http://your_server_ip:8000!

To run the application on production with nginx and uwsgi server, please refer to this tutorial that walks on setting up a typical Django application on Alibaba Cloud with nginx and uwsgi server included.

Conclusion

The code for the application is on GitHub. Feel free to raise issues on the repo and I will address them.

Reference:https://www.alibabacloud.com/blog/setup-and-deploy-geodjango-app-on-alibaba-cloud-part-2-completing-the-app_594613?spm=a2c41.12714435.0.0

Follow me to keep abreast with the latest technology news, industry insights, and developer trends. Alibaba Cloud website:https://www.alibabacloud.com