PostGIS Integration
Environment Setup
Docker Configuration
Below are the changes needed to set up the environment for PostGIS and GDAL.
Dockerfile Modifications
Add the necessary dependencies for GDAL:
# Install GDAL and related dependencies
RUN apt-get update && apt-get install -y binutils libproj-dev gdal-bin libgdal-dev
# Set environment variables for GDAL
ENV GDAL_LIBRARY_PATH=/usr/lib/libgdal.so
ENV GEOS_LIBRARY_PATH=/usr/lib/libgeos_c.so
docker-compose.yml Modifications
Replace the default database image with the official PostGIS image:
services:
db:
image: postgis/postgis:latest
restart: always
ports:
- "5433:5432"
env_file:
- .env
volumes:
- pgdata:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 10s
timeout: 5s
retries: 5
volumes:
pgdata:
PostGIS Integration in Django
Step 1: Use PointField and PolygonField in Models and Serializers
Below is an example of how to define models in Django that include geospatial fields such as PointField and PolygonField.
Models
from django.contrib.gis.db import models
class Location(models.Model):
name = models.CharField(max_length=100)
position = models.PointField() # Field to store a geospatial point
class Region(models.Model):
name = models.CharField(max_length=100)
area = models.PolygonField() # Field to store a geospatial polygon
Serializers and forms
If you are using serializers you can integrate this easily with
from rest_framework_gis.serializers import GeoFeatureModelSerializer
from .models import Location, Region
class LocationSerializer(GeoFeatureModelSerializer):
class Meta:
model = Location
fields = ('id', 'name', 'position')
geo_field = 'position'
class RegionSerializer(GeoFeatureModelSerializer):
class Meta:
model = Region
fields = ('id', 'name', 'area')
geo_field = 'area'
And they also provide the form alternative
from django import forms
from django.contrib.gis import forms as gis_forms
from .models import Location, Region
class LocationForm(forms.ModelForm):
position = gis_forms.PointField(widget=gis_forms.OSMWidget(attrs={
'map_width': 800,
'map_height': 500,
}))
class Meta:
model = Location
fields = ['name', 'position']
class RegionForm(forms.ModelForm):
area = gis_forms.PolygonField(widget=gis_forms.OSMWidget(attrs={
'map_width': 800,
'map_height': 500,
}))
class Meta:
model = Region
fields = ['name', 'area']
Example Requests to Create a Point and a Polygon
Create a Location (Point)
POST /api/locations/
Content-Type: application/json
{
"name": "Central Park",
"position": {
"type": "Point",
"coordinates": [-56.18816, -34.9011]
}
}
Create a Region (Polygon)
POST /api/regions/
Content-Type: application/json
{
"name": "Restricted Zone",
"area": {
"type": "Polygon",
"coordinates": [[
[-56.18816, -34.9011],
[-56.19000, -34.9000],
[-56.18900, -34.9020],
[-56.18816, -34.9011]
]]
}
}
Example Geospatial Queries
Find the K Nearest Points
from django.contrib.gis.db.models.functions import Distance
from django.contrib.gis.geos import Point
from .models import Location
# Define the reference point
reference = Point(-56.18816, -34.9011, srid=4326)
# Find the 5 nearest points
nearest_locations = Location.objects.annotate(
distance=Distance('position', reference)
).order_by('distance')[:5]
Find Points within a Certain Distance
from django.contrib.gis.measure import D
# Find locations within 1 km of the reference point
nearby_locations = Location.objects.filter(
position__distance_lte=(reference, D(km=1))
)
Check if a Point is Within a Polygon
from .models import Region
# Check if the point is within any region
point = Point(-56.18816, -34.9011, srid=4326)
regions = Region.objects.filter(area__contains=point)