geostore/import_export/exports.py
import glob
import json
import os
from tempfile import TemporaryDirectory
import fiona
from django.core.serializers import serialize
from fiona.crs import from_epsg
from geostore import GeometryTypes
from geostore import settings as app_settings
from geostore.import_export.helpers import make_zipfile_bytesio, get_serialized_properties
from geostore.renderers import KMLRenderer
class LayerExportMixin:
def to_geojson(self):
if not self.features.count():
return
return serialize('geojson',
self.features.all(),
fields=('properties',),
geometry_field='geom',
properties_field='properties')
def to_shapefile(self):
if not self.features.count():
return
with TemporaryDirectory() as shape_folder:
shapes = {}
# get all accepted types if geom_type not defined, else keep selected
type_to_check = GeometryTypes.shape_allowed_type_names() \
if not self.geom_type else \
[GeometryTypes(self.geom_type).name]
# Create one shapefile by kind of geometry
for geom_type in type_to_check:
schema = {
'geometry': geom_type,
'properties': self.layer_properties,
}
shapes[geom_type] = fiona.open(
shape_folder,
layer=geom_type,
mode='w',
driver='ESRI Shapefile',
schema=schema,
encoding='UTF-8',
crs=from_epsg(app_settings.INTERNAL_GEOMETRY_SRID)
)
# Export features to each kind of geometry
for feature in self.features.all():
shapes[feature.geom.geom_type].write({
'geometry': json.loads(feature.geom.json),
'properties': get_serialized_properties(self, feature.properties)
})
# Close fiona files
for geom_type, shape in shapes.items():
shape_size = len(shape)
shape.close()
# Delete empty shapes
if not shape_size:
for filename in glob.iglob(os.path.join(shape_folder, f'{geom_type}.*')):
os.remove(filename)
# Zip to BytesIO and return shape files
return make_zipfile_bytesio(shape_folder)
def to_kml(self):
from geostore.serializers import FeatureSerializer
if not self.features.count():
return
return KMLRenderer().render(FeatureSerializer(self.features.all(), many=True).data)