Start of creating kmz file, with entrance photos and links to expo.survex.com

This commit is contained in:
Martin Green 2023-05-08 01:10:43 +01:00
parent ea7c29a54e
commit f7fca58c57
8 changed files with 160 additions and 74 deletions

View File

@ -1,10 +1,15 @@
import os import os
import re import re
import subprocess import subprocess
import tempfile
import zipfile
import urllib
from bs4 import BeautifulSoup
from pathlib import Path from pathlib import Path
from django.core.exceptions import MultipleObjectsReturned, ObjectDoesNotExist from django.core.exceptions import MultipleObjectsReturned, ObjectDoesNotExist
from django.http import HttpResponse, HttpResponseNotFound, HttpResponseRedirect from django.http import HttpResponse, HttpResponseNotFound, HttpResponseRedirect, FileResponse
from django.shortcuts import render from django.shortcuts import render
from django.urls import NoReverseMatch, reverse from django.urls import NoReverseMatch, reverse
@ -17,6 +22,8 @@ from troggle.core.views import expo
from troggle.settings import CAVEDESCRIPTIONS, ENTRANCEDESCRIPTIONS from troggle.settings import CAVEDESCRIPTIONS, ENTRANCEDESCRIPTIONS
from troggle.parsers.caves import read_cave, read_entrance from troggle.parsers.caves import read_cave, read_entrance
from django.template import loader
from django.utils.safestring import mark_safe
from .auth import login_required_if_public from .auth import login_required_if_public
@ -628,3 +635,45 @@ def expo_kml(request):
}, },
content_type = "application/vnd.google-earth.kml+xml" content_type = "application/vnd.google-earth.kml+xml"
) )
def expo_kmz(request):
notablecaves = set(getnotablecaves())
#Zip file written to a file, to save this function using too much memory
with tempfile.TemporaryDirectory() as tmpdirname:
zippath = os.path.join(tmpdirname, 'expo.kmz')
with zipfile.ZipFile(zippath, 'w', compression=zipfile.ZIP_DEFLATED) as myzip:
entrances = []
for e in Entrance.objects.all():
html = loader.get_template("entrance_html.kml").render({"entrance": e}, request)
soup=BeautifulSoup(html)
for img in soup.find_all("img"):
#src_orig = img['src']
src = urllib.parse.urljoin(e.cavelist()[0].url.rpartition("/")[0] + "/", img['src'])
img['src'] = src
p = os.path.join(settings.EXPOWEB, src)
#print(e.cavelist()[0].url, e.cavelist()[0].url.rpartition("/")[0] + "/", src_orig, p)
if os.path.isfile(p):
myzip.write(p, src)
for a in soup.find_all("a"):
try:
ao = a['href']
aa = urllib.parse.urljoin(e.cavelist()[0].url.rpartition("/")[0] + "/", ao)
a['href'] = urllib.parse.urljoin("https://expo.survex.com/", aa)
print(e.cavelist()[0].url.rpartition("/")[0] + "/", ao, a['href'])
except:
pass
html = mark_safe(soup.prettify("utf-8").decode("utf-8"))
size = {True: "large", False:"small"}[bool(set(e.cavelist()) & notablecaves)]
entrances.append(loader.get_template("entrance.kml").render({"entrance": e, "html": html, "size": size}, request))
s = loader.get_template("expo.kml").render({"entrances": entrances}, request)
myzip.writestr("expo.kml", s)
for f in os.listdir(settings.KMZ_ICONS_PATH):
p = os.path.join(settings.KMZ_ICONS_PATH, f)
if os.path.isfile(p):
myzip.write(p, os.path.join("icons", f))
return FileResponse(open(zippath, 'rb'), content_type="application/vnd.google-earth.kmz .kmz")

BIN
kmz_icons/camp.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.5 KiB

BIN
kmz_icons/large_cave.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

BIN
kmz_icons/small_cave.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.4 KiB

10
templates/entrance.kml Normal file
View File

@ -0,0 +1,10 @@
{% if entrance.latlong %}
<Placemark>
<name>{{ entrance.slug }}</name>
<description><![CDATA[{{ html }}]]></description>
<styleUrl>#{{ size }}_cave</styleUrl>
<Point>
<coordinates>{{ entrance.latlong.1 }},{{ entrance.latlong.0 }},0</coordinates>
</Point>
</Placemark>
{% endif %}

View File

@ -0,0 +1,55 @@
<dl>
<a href="{{entrance.cavelist.0.url }}">Cave: {{entrance.cavelist.0.name }}</a>
{% if entrance.marking %}
<dt>Marking</dt><dd>{{ entrance.marking_val|safe }}</dd>
{% endif %}
{% if entrance.marking_comment %}
<dt>Marking Comment</dt><dd>{{ entrance.marking_comment|safe }}</dd>
{% endif %}
{% if entrance.findability %}
<dt>Findability</dt><dd>{{ entrance.findability_val|safe }}</dd>
{% endif %}
{% if entrance.findability_comment %}
<dt>Findability Comment</dt><dd>{{ entrance.findability_comment|safe }}</dd>
{% endif %}
{% if entrance.location_description %}
<dt>Location</dt><dd>{{ entrance.location_description|safe }}</dd>
{% endif %}
{% if entrance.approach %}
<dt>Approach</dt><dd>{{ entrance.approach|safe }}</dd>
{% endif %}
{% if entrance.map_description %}
<dt>Map</dt><dd>{{ entrance.map_description|safe }}</dd>
{% endif %}
{% if entrance.underground_description %}
<dt>Underground</dt><dd>{{ entrance.underground_description|safe }}</dd>
{% endif %}
{% if entrance.photo %}
<dt>Photo</dt><dd>{{ entrance.photo|safe }}</dd>
{% endif %}
{% if entrance.entrance_description %}
<dt>Description</dt><dd>{{ entrance.entrance_description|safe }}</dd>
{% endif %}
{% if entrance.explorers %}
<dt>Explorers</dt><dd>{{ entrance.explorers|safe }}</dd>
{% endif %}
{% if entrance.northing %}
<dt>Location</dt><dd>?BMN? Northing: {{ entrance.northing|safe }}, Easting: {{ entrance.easting|safe }}, {{ entrance.alt|safe }}m</dd>
{% endif %}
{% if entrance.tag_station %}
<dt>Tag Location</dt><dd>{{ entrance.tag_station }} {{ entrance.tag.latlong.0|floatformat:5 }}N {{ entrance.tag.latlong.1|floatformat:5 }}E - UTM33 {{ entrance.tag.y|floatformat:0 }}, {{ entrance.tag.x|floatformat:0 }}, {{ entrance.tag.z|floatformat:0 }}m</dd>
{% endif %}
{% if entrance.bearings %}
<dt>Bearings</dt><dd>{{ entrance.bearings|safe }}</dd>
{% endif %}
{% if entrance.exact_station %}
<dt>Exact Station</dt><dd>{{ entrance.exact_station|safe }} {{ entrance.exact_location.latlong.0|floatformat:5 }}N {{ entrance.exact_location.latlong.1|floatformat:5 }}E - UTM33 {{ entrance.exact_location.y|floatformat:0 }}, {{ entrance.exact_location.x|floatformat:0 }}, {{ entrance.exact_location.z|floatformat:0 }}m</dd>
{% endif %}
{% if entrance.other_station %}
<dt>Other Station</dt><dd>{{ entrance.other_station|safe }}
{% if entrance.other_description %}
- {{ entrance.other_description|safe }}
{% endif %} {{ entrance.other_location.latlong.0|floatformat:5 }}N {{ entrance.other_location.latlong.1|floatformat:5 }}E - UTM33 {{ entrance.other_location.y|floatformat:0 }}, {{ entrance.other_location.x|floatformat:0 }}, {{ entrance.other_location.z|floatformat:0 }}m
</dd>
{% endif %}
</dl>

View File

@ -2,104 +2,75 @@
<kml xmlns="http://www.opengis.net/kml/2.2" xmlns:gx="http://www.google.com/kml/ext/2.2" xmlns:kml="http://www.opengis.net/kml/2.2" xmlns:atom="http://www.w3.org/2005/Atom"> <kml xmlns="http://www.opengis.net/kml/2.2" xmlns:gx="http://www.google.com/kml/ext/2.2" xmlns:kml="http://www.opengis.net/kml/2.2" xmlns:atom="http://www.w3.org/2005/Atom">
<Document> <Document>
<name>Expo.KML</name> <name>Expo.KML</name>
<Style id="default0"> <Style id="small_cave_">
<IconStyle> <IconStyle>
<scale>0.7</scale> <scale>1.0</scale>
<Icon> <Icon>
<href>http://maps.google.com/mapfiles/kml/shapes/placemark_circle.png</href> <href>icons/small_cave.png</href>
</Icon> </Icon>
</IconStyle> </IconStyle>
<LabelStyle> <LabelStyle>
<scale>0.7</scale> <scale>0.7</scale>
</LabelStyle> </LabelStyle>
</Style> </Style>
<Style id="hl"> <Style id="small_cave_hl">
<IconStyle> <IconStyle>
<scale>0.84</scale> <scale>2.0</scale>
<Icon> <Icon>
<href>http://maps.google.com/mapfiles/kml/shapes/placemark_circle_highlight.png</href> <href>icons/small_cave.png</href>
</Icon> </Icon>
</IconStyle> </IconStyle>
<LabelStyle> <LabelStyle>
<scale>0.7</scale> <scale>0.7</scale>
</LabelStyle> </LabelStyle>
</Style> </Style>
<StyleMap id="default"> <StyleMap id="small_cave">
<Pair> <Pair>
<key>normal</key> <key>normal</key>
<styleUrl>#default0</styleUrl> <styleUrl>#small_cave_</styleUrl>
</Pair> </Pair>
<Pair> <Pair>
<key>highlight</key> <key>highlight</key>
<styleUrl>#hl</styleUrl> <styleUrl>#small_cave_hl</styleUrl>
</Pair>
</StyleMap>
<Style id="large_cave_">
<IconStyle>
<scale>1.0</scale>
<Icon>
<href>icons/large_cave.png</href>
</Icon>
</IconStyle>
<LabelStyle>
<scale>0.7</scale>
</LabelStyle>
</Style>
<Style id="large_cave_hl">
<IconStyle>
<scale>2.0</scale>
<Icon>
<href>icons/large_cave.png</href>
</Icon>
</IconStyle>
<LabelStyle>
<scale>0.7</scale>
</LabelStyle>
</Style>
<StyleMap id="large_cave">
<Pair>
<key>normal</key>
<styleUrl>#large_cave_</styleUrl>
</Pair>
<Pair>
<key>highlight</key>
<styleUrl>#large_cave_hl</styleUrl>
</Pair> </Pair>
</StyleMap> </StyleMap>
<Folder> <Folder>
<name>Expo.KML</name> <name>Expo.KML</name>
{% for entrance in entrances %} {% for entrance in entrances %}
{% if entrance.latlong %} {{ entrance }}
<Placemark>
<name>{{ entrance.slug }}</name>
<description><![CDATA[ <dl>
{% if entrance.marking %}
<dt>Marking</dt><dd>{{ entrance.marking_val|safe }}</dd>
{% endif %}
{% if entrance.marking_comment %}
<dt>Marking Comment</dt><dd>{{ entrance.marking_comment|safe }}</dd>
{% endif %}
{% if entrance.findability %}
<dt>Findability</dt><dd>{{ entrance.findability_val|safe }}</dd>
{% endif %}
{% if entrance.findability_comment %}
<dt>Findability Comment</dt><dd>{{ entrance.findability_comment|safe }}</dd>
{% endif %}
{% if entrance.location_description %}
<dt>Location</dt><dd>{{ entrance.location_description|safe }}</dd>
{% endif %}
{% if entrance.approach %}
<dt>Approach</dt><dd>{{ entrance.approach|safe }}</dd>
{% endif %}
{% if entrance.map_description %}
<dt>Map</dt><dd>{{ entrance.map_description|safe }}</dd>
{% endif %}
{% if entrance.underground_description %}
<dt>Underground</dt><dd>{{ entrance.underground_description|safe }}</dd>
{% endif %}
{% if entrance.photo %}
<dt>Photo</dt><dd>{{ entrance.photo|safe }}</dd>
{% endif %}
{% if entrance.entrance_description %}
<dt>Description</dt><dd>{{ entrance.entrance_description|safe }}</dd>
{% endif %}
{% if entrance.explorers %}
<dt>Explorers</dt><dd>{{ entrance.explorers|safe }}</dd>
{% endif %}
{% if entrance.northing %}
<dt>Location</dt><dd>?BMN? Northing: {{ entrance.northing|safe }}, Easting: {{ entrance.easting|safe }}, {{ entrance.alt|safe }}m</dd>
{% endif %}
{% if entrance.tag_station %}
<dt>Tag Location</dt><dd>{{ entrance.tag_station }} UTM33 {{ entrance.tag.y|floatformat:0 }}, {{ entrance.tag.x|floatformat:0 }}, {{ entrance.tag.z|floatformat:0 }}m</dd>
{% endif %}
{% if entrance.bearings %}
<dt>Bearings</dt><dd>{{ entrance.bearings|safe }}</dd>
{% endif %}
{% if entrance.exact_station %}
<dt>Exact Station</dt><dd>{{ entrance.exact_station|safe }} UTM33 {{ entrance.exact_location.y|floatformat:0 }}, {{ entrance.exact_location.x|floatformat:0 }}, {{ entrance.exact_location.z|floatformat:0 }}m</dd>
{% endif %}
{% if entrance.other_station %}
<dt>Other Station</dt><dd>{{ entrance.other_station|safe }}
{% if entrance.other_description %}
- {{ entrance.other_description|safe }}
{% endif %} UTM33 {{ entrance.other_location.y|floatformat:0 }}, {{ entrance.other_location.x|floatformat:0 }}, {{ entrance.other_location.z|floatformat:0 }}m
</dd>
{% endif %}
</dl> ]]></description>
<styleUrl>#default</styleUrl>
<Point>
<coordinates>{{ entrance.latlong.1 }},{{ entrance.latlong.0 }},0</coordinates>
</Point>
</Placemark>
{% endif %}
{% endfor %} {% endfor %}
</Folder> </Folder>
</Document> </Document>

View File

@ -8,7 +8,7 @@ from troggle.core.views import statistics, survex
from troggle.core.views.auth import expologin, expologout from troggle.core.views.auth import expologin, expologout
from troggle.core.views.caves import (cave3d, caveEntrance, caveindex, from troggle.core.views.caves import (cave3d, caveEntrance, caveindex,
cavepage, caveQMs, edit_cave, cave_debug, cavepage, caveQMs, edit_cave, cave_debug,
edit_entrance, get_entrances, qm, expo_kml) edit_entrance, get_entrances, qm, expo_kml, expo_kmz)
from troggle.core.views.drawings import dwgallfiles, dwgfilesingle from troggle.core.views.drawings import dwgallfiles, dwgfilesingle
from troggle.core.views.editor_helpers import image_selector, new_image_form from troggle.core.views.editor_helpers import image_selector, new_image_form
from troggle.core.views.expo import (editexpopage, expofiles_redirect, from troggle.core.views.expo import (editexpopage, expofiles_redirect,
@ -232,6 +232,7 @@ trogglepatterns = [
re_path(r'^new_image_form/(?P<path>.*)', new_image_form, name = 'new_image_form'), re_path(r'^new_image_form/(?P<path>.*)', new_image_form, name = 'new_image_form'),
re_path(r'^expo.kml', expo_kml, name = 'expo.kml'), re_path(r'^expo.kml', expo_kml, name = 'expo.kml'),
re_path(r'^expo.kmz', expo_kmz, name = 'expo.kmz'),
# Final catchall which also serves expoweb handbook pages and imagestiny # Final catchall which also serves expoweb handbook pages and imagestiny
re_path(r'^(.*)$', expopage, name="expopage"), # CATCHALL assumed relative to EXPOWEB re_path(r'^(.*)$', expopage, name="expopage"), # CATCHALL assumed relative to EXPOWEB