GeoDjango QuerySet to KML
models/point_models.py
from django.contrib.gis.db import models
# Create your models here.
class PointManager(models.Manager):
pass
class Point(models.Model):
"""
Model representing a geometry point
"""
objects = PointManager()
POINT_TYPE = (
('LOSS', 'LOSS'),
('ODF', 'ODF'),
('OFC_CLOSURE', 'OFC_CLOSURE'),
('LOOP', 'LOOP'),
('POLE', 'POLE'),
('PB', 'PB'),
('MAINHOLE', 'MAINHOLE'),
('RISER', 'RISER'),
('CUSTOMER', 'CUSTOMER'),
('NODE', 'NODE'),
('EQUIPMENT', 'EQUIPMENT'),
('PATCH', 'PATCH'),
)
created_at = models.DateTimeField(auto_now_add=True, blank=True)
last_modified_at = models.DateTimeField(auto_now=True, blank=True)
inactive_at = models.DateTimeField(blank=True, null=True)
active = models.BooleanField(default=True)
circuit_id = models.CharField(max_length=64, null=True)
description = models.TextField(
max_length=1000,
blank=True,
null=True,
help_text="Enter a brief description of the point"
)
geom = models.PointField(srid=4326, null=True,)
longitude = models.FloatField(null=True)
latitude = models.FloatField(null=True)
layer_name = models.CharField(max_length=384,blank=True,null=True)
name = models.CharField(max_length=384)
POINT_CATEGORY = (
('AERIAL', 'AERIAL'),
('UNDERGROUND', 'UNDERGROUND'),
)
point_category = models.CharField(
max_length=32,
choices=POINT_CATEGORY,
default='AERIAL',
)
point_type = models.CharField(
max_length=16,
choices=POINT_TYPE,
default='OFC_CLOSURE',
)
POINT_OPERATOR = (
('ITEL', 'ITEL'),
('NBTC', 'NBTC'),
('PEA', 'PEA'),
('MEA', 'MEA'),
)
operator = models.CharField(
max_length=16,
choices=POINT_OPERATOR,
default='ITEL',
)
service_order = models.CharField(max_length=64, null=True)
validated = models.BooleanField(default=False)
work_order = models.CharField(max_length=64, null=True)
def __str__(self):
"""
String for representing the Model object.
"""
return f'{self.pk} ({self.name})'
def natural_key(self):
return (self.pk, self.name)
models/line_models.py
from django.contrib.gis.db import models
class Line(models.Model):
"""
Model representing a geometry line string
"""
objects = LineManager()
LINE_TYPE = (
('ADSS', 'ADSS'),
('DROPWIRE', 'DROPWIRE'),
('FIG8', 'FIG8'),
('SELFSUPPORT', 'SELFSUPPORT'),
('ARSS', 'ARSS'),
)
created_at = models.DateTimeField(auto_now_add=True, blank=True)
last_modified_at = models.DateTimeField(auto_now=True, blank=True)
inactive_at = models.DateTimeField(blank=True, null=True)
active = models.BooleanField(default=True)
circuit_id = models.CharField(max_length=64, null=True, blank=True,)
core = models.PositiveSmallIntegerField(default=2, validators=[MaxValueValidator(256)])
description = models.TextField(
max_length=1000,
blank=True,
null=True,
help_text="Enter a brief description of the line"
)
geom = models.LineStringField(srid=4326, null=True, blank=True,)
length = models.FloatField(default=0.00)
layer_name = models.CharField(max_length=254, blank=True, null=True,)
LINE_CATEGORY = (
('AERIAL', 'AERIAL'),
('UNDERGROUND', 'UNDERGROUND'),
)
line_category = models.CharField(
max_length=32,
choices=LINE_CATEGORY,
default='AERIAL',
)
LINE_STATUS = (
('USED', 'USED'),
('DAMAGE', 'DAMAGE'),
('UNDER_CONSTRUCTION', 'UNDER_CONSTRUCTION'),
)
line_status = models.CharField(
max_length=32,
choices=LINE_STATUS,
default='USED',
)
line_type = models.CharField(
max_length=16,
choices=LINE_TYPE,
blank=True,
)
name = models.CharField(max_length=254)
"""
use get-or-create create m2m2 related_cores
https://docs.djangoproject.com/en/2.1/ref/models/querysets/#get-or-create
"""
LINE_OPERATOR = (
('ITEL', 'ITEL'),
('NBTC', 'NBTC'),
('PEA', 'PEA'),
('MEA', 'MEA'),
)
operator = models.CharField(
max_length=16,
choices=LINE_OPERATOR,
default='ITEL',
)
otdr_len = models.FloatField(default=0.00)
service_order = models.CharField(max_length=64, null=True, blank=True,)
source_poi = models.ForeignKey(
'Point',
related_name='source_poi',
on_delete=models.SET_NULL,
null=True,
blank=True,
)
target_poi = models.ForeignKey(
'Point',
related_name='target_poi',
on_delete=models.SET_NULL,
null=True,
blank=True,
)
validated = models.BooleanField(default=False)
work_order = models.CharField(max_length=64, null=True, blank=True,)
def __str__(self):
"""
String for representing the Model object.
"""
return self.name
def natural_key(self):
return (self.name)
models/thaadm1_models.py
from django.contrib.gis.db import models
class THAAdm1(models.Model):
THAADM1_REGION = (
('CENTRAL', 'CENTRAL'),
('EAST', 'EAST'),
('METRO', 'METRO'),
('UP_NORTH', 'UP_NORTH'),
('DOWN_NORTH', 'DOWN_NORTH'),
('UP_NORTHEAST', 'UP_NORTHEAST'),
('DOWN_NORTHEAST', 'DOWN_NORTHEAST'),
('SOUTH', 'SOUTH'),
('WEST', 'WEST'),
)
region = models.CharField(
max_length=16,
choices=THAADM1_REGION,
blank=True,
null=True,
)
iso = models.CharField(max_length=254)
prov_namt = models.CharField(max_length=80)
adm1name = models.CharField(max_length=254)
adm1code = models.CharField(max_length=254)
adm0name = models.CharField(max_length=50)
admin0code = models.CharField(max_length=2)
geom = models.MultiPolygonField(srid=4326)
short_label = models.CharField(max_length=2, blank=True, null=True,)
class Meta:
ordering = ['-prov_namt']
def __str__(self):
"""
String for representing the Model object.
"""
return f'{self.adm1code} :=: {self.prov_namt}'
views/geom_export_to_kml_views.py
#importing the object django.conf.settings
from django.conf import settings
from django.core.files.storage import FileSystemStorage
from django.db.models import Q
from optnet.models import Line, Point, THAAdm1
import os
import json
import requests
import xml.dom.minidom
def create_point_data_element(kml_doc, point, ext_element):
point_dict=point.__dict__
point_fields = ['id', 'name', 'point_category',
'point_type', 'operator', 'service_order', 'work_order', 'description']
# Loop through the point attribute and create a element for every field that has a value.
for key in point_fields:
if point_dict[key]:
data_element = kml_doc.createElement('Data')
data_element.setAttribute('name', key)
value_element = kml_doc.createElement('value')
data_element.appendChild(value_element)
value_text = kml_doc.createTextNode(str(point_dict[key]))
data_element.appendChild(value_text)
ext_element.appendChild(data_element)
return ext_element
def create_placemark_point(kml_doc, point):
# <Placemark> ...</Placemark>
placemark_element = kml_doc.createElement('Placemark')
ext_element = kml_doc.createElement('ExtendedData')
placemark_element.appendChild(ext_element)
# <name> ...</name>
name_element = kml_doc.createElement('name')
name_element.appendChild(kml_doc.createTextNode(str(point.name)))
placemark_element.appendChild(name_element)
# <ExtendedData> ...</ExtendedData>
create_point_data_element(kml_doc, point, ext_element)
# <Point> ...</Point>
point_element = kml_doc.createElement('Point')
placemark_element.appendChild(point_element)
x = point.geom.x
y = point.geom.y
coordinates = str(x)+','+str(y)
# <coordinates> ...</coordinates>
coor_element = kml_doc.createElement('coordinates')
coor_element.appendChild(kml_doc.createTextNode(coordinates))
point_element.appendChild(coor_element)
return placemark_element
def create_line_data_element(kml_doc, line, ext_element):
line_dict=line.__dict__
line_fields = ['id', 'name', 'line_type', 'length', 'line_category',
'core', 'service_order', 'work_order', 'description', 'operator']
# Loop through the point attribute and create a element for every field that has a value.
for key in line_fields:
if line_dict[key]:
data_element = kml_doc.createElement('Data')
data_element.setAttribute('name', key)
value_element = kml_doc.createElement('value')
data_element.appendChild(value_element)
value_text = kml_doc.createTextNode(str(line_dict[key]))
data_element.appendChild(value_text)
ext_element.appendChild(data_element)
return ext_element
def style_linestring(kml_doc, placemark_element):
# <Style> ...</Style>
style_element = kml_doc.createElement('Style')
placemark_element.appendChild(style_element)
# <LineStyle> ...</LineStyle>
line_style_element = kml_doc.createElement('LineStyle')
style_element.appendChild(line_style_element)
# <color> ...</color>
color_element = kml_doc.createElement('color')
color_element.appendChild(kml_doc.createTextNode('7faaff7f'))
line_style_element.appendChild(color_element)
# <width> ...</width>
width_element = kml_doc.createElement('width')
width_element.appendChild(kml_doc.createTextNode('6'))
line_style_element.appendChild(width_element)
return placemark_element
def create_placemark_linestring(kml_doc, line):
# <Placemark> ...</Placemark>
placemark_element = kml_doc.createElement('Placemark')
ext_element = kml_doc.createElement('ExtendedData')
placemark_element.appendChild(ext_element)
# style line string
placemark_element = style_linestring(kml_doc, placemark_element)
# <name> ...</name>
name_element = kml_doc.createElement('name')
name_element.appendChild(kml_doc.createTextNode(str(line.name)))
placemark_element.appendChild(name_element)
# <ExtendedData> ...</ExtendedData>
create_line_data_element(kml_doc, line, ext_element)
# <LineString> ...</LineString>
line_element = kml_doc.createElement('LineString')
placemark_element.appendChild(line_element)
coordinates = line.geom.kml.replace("<LineString><coordinates>", "").replace("</coordinates></LineString>", "")
# <coordinates> ...</coordinates>
coor_element = kml_doc.createElement('coordinates')
coor_element.appendChild(kml_doc.createTextNode(coordinates))
line_element.appendChild(coor_element)
return placemark_element
def create_kml_doc(adm1):
"""
This tutorial uses code from Geocoding Addresses for Use in KML.
https://developers.google.com/kml/articles/geocodingforkml
https://developers.google.com/kml/articles/csvtokml
"""
# This constructs the KML document from the CSV file.
kml_doc = xml.dom.minidom.Document()
kml_element = kml_doc.createElementNS('http://earth.google.com/kml/2.2', 'kml')
kml_element.setAttribute('xmlns','http://earth.google.com/kml/2.2')
kml_element = kml_doc.appendChild(kml_element)
document_element = kml_doc.createElement('Document')
document_element = kml_element.appendChild(document_element)
# get points within adm1 geom
points_in_adm1 = Point.objects.filter(geom__within=adm1.geom)
for p in points_in_adm1:
placemark_element = create_placemark_point(kml_doc, p)
document_element.appendChild(placemark_element)
# get lines within or intersects adm1 geom
lines_in_adm1 = Line.objects.filter(
Q(geom__within=adm1.geom) | Q(geom__intersects=adm1.geom))
for line in lines_in_adm1:
placemark_element = create_placemark_linestring(kml_doc, line)
document_element.appendChild(placemark_element)
path = os.path.join(settings.MEDIA_ROOT, 'kml/')
adm1_name = str(adm1.adm1name).replace(" ", "")
file_name = path+str(adm1.adm1code)+'_'+adm1_name+'.kml'
with open(file_name, "wb") as outfile:
outfile.write(kml_doc.toprettyxml(encoding="UTF-8"))
def create_kml_doc_by_adm1():
adm1_all = THAAdm1.objects.all()
for adm1 in adm1_all:
create_kml_doc(adm1)