From ab79a43afa3b86181c3eaf7c327d54a78c18a8f4 Mon Sep 17 00:00:00 2001 From: Philip Sargent Date: Sun, 10 Sep 2023 15:42:36 +0300 Subject: [PATCH] Removed class Area, use Cave.areacode Cave.subarea --- core/admin.py | 4 +- core/models/caves.py | 44 +++----------- core/views/caves.py | 8 +-- core/views/prospect.py | 12 ++-- core/views/survex.py | 21 +++---- parsers/caves.py | 127 ++++++++++++--------------------------- parsers/locations.py | 4 +- parsers/survex.py | 2 +- templates/cave.html | 10 ++- templates/survexdir.html | 2 +- 10 files changed, 75 insertions(+), 159 deletions(-) diff --git a/core/admin.py b/core/admin.py index 43aa744..880d163 100644 --- a/core/admin.py +++ b/core/admin.py @@ -2,7 +2,7 @@ from django.contrib import admin from django.core import serializers from django.http import HttpResponse -from troggle.core.models.caves import Area, Cave, CaveAndEntrance, Entrance +from troggle.core.models.caves import Cave, CaveAndEntrance, Entrance from troggle.core.models.logbooks import QM, LogbookEntry, PersonLogEntry, CaveSlug from troggle.core.models.survex import ( DrawingFile, @@ -135,7 +135,7 @@ class WalletAdmin(TroggleModelAdmin): admin.site.register(Cave, CaveAdmin) -admin.site.register(Area) +#admin.site.register(Area) admin.site.register(CaveAndEntrance) admin.site.register(Entrance, EntranceAdmin) admin.site.register(CaveSlug) diff --git a/core/models/caves.py b/core/models/caves.py index 3821387..0ede2b1 100644 --- a/core/models/caves.py +++ b/core/models/caves.py @@ -32,33 +32,15 @@ todo = """ - Can we rewrite things to eliminate the CaveSlug and objects? Surely foreign keys work fine ?! -- Why do we have CaveAndEntrance objects ? Surely entranceletter belong son the Entrance object? +- Why do we have CaveAndEntrance objects ? Surely entranceletter belongs on the Entrance object? - move the aliases list from the code and put into an editable file - Restore constraint: unique_together = (("area", "kataster_number"), ("area", "unofficial_number")) + or replace by a unique 'slug' field, better. """ -class Area(TroggleModel): - short_name = models.CharField(max_length=100) - name = models.CharField(max_length=200, blank=True, null=True) - description = models.TextField(blank=True, null=True) - super = models.ForeignKey("Area", blank=True, null=True, on_delete=models.SET_NULL) - - def __str__(self): - if self.super: - return str(self.super) + " - " + str(self.short_name) - else: - return str(self.short_name) - - def kat_area(self): - if self.short_name in ["1623", "1626", "1624", "1627"]: - return self.short_name - elif self.super: - return self.super.kat_area() - - class CaveAndEntrance(models.Model): """This class is ONLY used to create a FormSet for editing the cave and all its entrances in one form. @@ -82,7 +64,8 @@ class CaveAndEntrance(models.Model): class Cave(TroggleModel): # too much here perhaps, - area = models.ManyToManyField(Area, blank=False) + areacode = models.CharField(max_length=4, blank=True, null=True) # could use models.IntegerChoices + subarea = models.CharField(max_length=10, blank=True, null=True) # 9, 8c etc. depth = models.CharField(max_length=100, blank=True, null=True) description_file = models.CharField(max_length=200, blank=True, null=True) entrances = models.ManyToManyField("Entrance", through="CaveAndEntrance") @@ -97,7 +80,7 @@ class Cave(TroggleModel): notes = models.TextField(blank=True, null=True) official_name = models.CharField(max_length=160) references = models.TextField(blank=True, null=True) - survex_file = models.CharField(max_length=100, blank=True, null=True) # should be a foreign key + survex_file = models.CharField(max_length=100, blank=True, null=True) # should be a foreign key? survey = models.TextField(blank=True, null=True) underground_centre_line = models.TextField(blank=True, null=True) underground_description = models.TextField(blank=True, null=True) @@ -192,12 +175,7 @@ class Cave(TroggleModel): return qms # a QuerySet def kat_area(self): - try: - for a in self.area.all(): - if a.kat_area(): - return a.kat_area() - except: - return "" + return self.areacode def entrances(self): return CaveAndEntrance.objects.filter(cave=self) @@ -258,15 +236,7 @@ class Cave(TroggleModel): return (filepath, content, "utf8") def getArea(self): - areas = self.area.all() - lowestareas = list(areas) - for area in areas: - if area.super in areas: - try: - lowestareas.remove(area.super) - except: - pass - return lowestareas[0] + return self.areacode class Entrance(TroggleModel): MARKING_CHOICES = ( diff --git a/core/views/caves.py b/core/views/caves.py index a002a0e..250ae0e 100644 --- a/core/views/caves.py +++ b/core/views/caves.py @@ -124,10 +124,10 @@ def getnotablecaves(): def caveindex(request): - #Cave.objects.all() - caves1623 = list(Cave.objects.filter(area__short_name="1623")) - caves1626 = list(Cave.objects.filter(area__short_name="1626")) - caves1627 = list(Cave.objects.filter(area__short_name="1627")) + + caves1623 = list(Cave.objects.filter(areacode="1623")) + caves1626 = list(Cave.objects.filter(areacode="1626")) + caves1627 = list(Cave.objects.filter(areacode="1627")) caves1623.sort(key=caveKey) caves1626.sort(key=caveKey) caves1627.sort(key=caveKey) diff --git a/core/views/prospect.py b/core/views/prospect.py index a538ab6..1eb82cd 100644 --- a/core/views/prospect.py +++ b/core/views/prospect.py @@ -4,7 +4,7 @@ from django.http import HttpResponse from django.shortcuts import render import troggle.settings as settings -from troggle.core.models.caves import Area, Cave, Entrance +from troggle.core.models.caves import Cave, Entrance from troggle.core.views.caves import caveKey # from pathlib import Path @@ -68,11 +68,11 @@ def prospecting(request): return render(request, "errors/disabled.html", {"message": message}) areas = [] - for key, name in AREANAMES: - a = Area.objects.get(short_name=key) # assumes unique - caves = list(a.cave_set.all()) - caves.sort(key=caveKey) - areas.append((name, a, caves)) + caves = Cave.objects.all() + + for c in caves: + if c.subarea in AREANAMES: + areas.append((AREANAMES[c.subarea], subarea, c)) return render(request, "prospecting.html", {"areas": areas}) diff --git a/core/views/survex.py b/core/views/survex.py index a69c5d3..b00aed0 100644 --- a/core/views/survex.py +++ b/core/views/survex.py @@ -574,15 +574,15 @@ def survexcaveslist(request): subdircaves = [] fnumlist = [] - for area in ["1623", "1626", "1624", "1627"]: - cavesdir = get_survexareapath(area) - arealist = sorted([(area, -int(re.match(r"\d*", f).group(0) or "0"), f) for f in os.listdir(cavesdir)]) + for areacode in ["1623", "1626", "1624", "1627"]: + cavesdir = get_survexareapath(areacode) + arealist = sorted([(areacode, -int(re.match(r"\d*", f).group(0) or "0"), f) for f in os.listdir(cavesdir)]) fnumlist += arealist # print(fnumlist) # go through the list and identify the contents of each cave directory - for area, num, cavedir in fnumlist: + for areacode, num, cavedir in fnumlist: # these have sub dirs /cucc/ /arge/ /old/ but that is no reason to hide them in this webpage # so these are now treated the same as 142 and 113 which also have a /cucc/ sub dir @@ -593,18 +593,17 @@ def survexcaveslist(request): # which usually but not always true. e.g. caves-1623/78/allkaese.svx not caves-1623/78/78.svx # which is why we now also pass through the cavedir - # Still fails for loutitohoehle etc even though this is set correctly when the pending cave is created - cavesdir = get_survexareapath(area) + cavesdir = get_survexareapath(areacode) gcavedir = os.path.join(cavesdir, cavedir) if os.path.isdir(gcavedir) and cavedir[0] != ".": subdirs, subsvx = identifycavedircontents(gcavedir) check_cave_registered( - area, cavedir + areacode, cavedir ) # should do this only once per database load or it will be slow survdirobj = [] for lsubsvx in subsvx: - survdirobj.append(("caves-" + area + "/" + cavedir + "/" + lsubsvx, lsubsvx)) + survdirobj.append(("caves-" + areacode + "/" + cavedir + "/" + lsubsvx, lsubsvx)) # caves with subdirectories if subdirs: @@ -614,7 +613,7 @@ def survexcaveslist(request): # assert not dsubdirs # handle case of empty sub directory lsurvdirobj = [] for lsubsvx in dsubsvx: - lsurvdirobj.append(("caves-" + area + "/" + cavedir + "/" + subdir + "/" + lsubsvx, lsubsvx)) + lsurvdirobj.append(("caves-" + areacode + "/" + cavedir + "/" + subdir + "/" + lsubsvx, lsubsvx)) if len(dsubsvx) >= 1: subsurvdirs.append( (subdir, lsurvdirobj[0], lsurvdirobj[0:]) @@ -683,7 +682,7 @@ def survexcavesingle(request, cave_shortname): else: return render(request, "errors/svxcaves404.html", {"settings": settings, "cave": cave_shortname}) -def check_cave_registered(area, survex_cave): +def check_cave_registered(areacode, survex_cave): """Checks whether a cave has been properly registered when it is found in the Loser repo This should really be called by databaseReset not here in a view Currently Caves are only registered if they are listed in :expoweb: settings.CAVEDESCRIPTIONS @@ -699,7 +698,7 @@ def check_cave_registered(area, survex_cave): except MultipleObjectsReturned: caves = Cave.objects.filter(kataster_number=survex_cave) for c in caves: - if str(c) == area + "-" + survex_cave: + if str(c) == areacode + "-" + survex_cave: return str(c) # just get the first that matches return None # many returned but none in correct area diff --git a/parsers/caves.py b/parsers/caves.py index 6850a1c..f70cdcd 100644 --- a/parsers/caves.py +++ b/parsers/caves.py @@ -8,7 +8,7 @@ from pathlib import Path from django.conf import settings from django.db import transaction -from troggle.core.models.caves import Area, Cave, CaveAndEntrance, Entrance, GetCaveLookup +from troggle.core.models.caves import Cave, CaveAndEntrance, Entrance, GetCaveLookup from troggle.core.models.logbooks import CaveSlug from troggle.core.models.troggle import DataIssue from troggle.settings import CAVEDESCRIPTIONS, ENTRANCEDESCRIPTIONS, EXPOWEB, SURVEX_DATA @@ -99,36 +99,6 @@ def set_dummy_entrance(id, slug, cave, msg="DUMMY"): # DataIssue.objects.create(parser="entrances", message=message, url=f"{cave.url}") # print(message) -def make_areas(): - print(" - Creating Areas 1623, 1624, 1627 and 1626") - # This crashes on the server with MariaDB even though a null parent is explicitly allowed. - area_1623 = Area.objects.create(short_name="1623", super=None) - area_1623.save() - area_1624 = Area.objects.create(short_name="1624", super=None) - area_1624.save() - area_1626 = Area.objects.create(short_name="1626", super=None) - area_1626.save() - area_1627 = Area.objects.create(short_name="1627", super=None) - area_1627.save() - -def get_area(areanum): - """Given the number as a string, return the area object - """ - a = Area.objects.all() - if len(a) == 0: - make_areas() - - area = Area.objects.get(short_name="1623") # default - - if areanum == "1623": - area = Area.objects.get(short_name="1623") - if areanum == "1624": - area = Area.objects.get(short_name="1624") - if areanum == "1626": - area = Area.objects.get(short_name="1626") - if areanum == "1627": - area = Area.objects.get(short_name="1627") - return area def create_new_cave(svxpath, msg=None): """This is called only when a new survex file is edited online which has a path on the @@ -145,29 +115,29 @@ def create_new_cave(svxpath, msg=None): print(f"parts {parts}, {a}, {caveid}") # double check if a[0:3] == "162": - areanum = a[0:4] - url = f"{areanum}/{caveid}.html" # Note we are appending the .html as we are believe in backwards compatability. - #url = f"{areanum}/{a[5:]}.html" # This is original code, but a above is only defined as being 4 characters long, so it did not make sense and produced non unique urls + areacode = a[0:4] + url = f"{areacode}/{caveid}.html" # Note we are appending the .html as we are believe in backwards compatability. + #url = f"{areacode}/{a[5:]}.html" # This is original code, but a above is only defined as being 4 characters long, so it did not make sense and produced non unique urls else: print(f"WARNING: parsers/caves/create_new_cave called with svxpath '{svxpath}'. Surely it should start 'caves-162*'? {msg}") - areanum = "1623" + areacode = "1623" url = f"1623/{caveid}.html" #url = f"1623/{k}.html" # This is original code, but a above is only defined as being 4 characters long, so it did not make sense and produced non unique urls - k = f"{areanum}-{caveid}" - area = get_area(areanum) + k = f"{areacode}-{caveid}" - caves = Cave.objects.filter(unofficial_number=caveid, area =areanum) + + caves = Cave.objects.filter(unofficial_number=caveid, areacode =areacode) if caves: - message = f" ! Already exists, caveid:{k} in area {areanum} {caves} - {msg}" + message = f" ! Already exists, caveid:{k} in areacode {areacode} {caves} - {msg}" DataIssue.objects.create(parser="caves", message=message) print(message) return caves[0] try: - cave = do_pending_cave(k, caveid, url, area, msg) + cave = do_pending_cave(k, caveid, url, areacode, msg) except: - message = f" ! Error. Cannot create pending cave and entrance, pending-id:{k} in area {areanum} - {msg}" + message = f" ! Error. Cannot create pending cave and entrance, pending-id:{k} in area {areacode} - {msg}" DataIssue.objects.create(parser="caves", message=message) print(message) raise @@ -175,14 +145,15 @@ def create_new_cave(svxpath, msg=None): # we know what the survex file is, we don't need to use the guess. # But this sets the survex file on he cave from the first one we find, not necessarily the best survex file for this cave cave.survex_file=survex_file + cave.areacode=areacode cave.save() return cave -def do_ARGE_cave(slug, caveid, url, area, svxid): +def do_ARGE_cave(slug, caveid, url, areacode, svxid): """Only called by survex parser. Creates a new Cave object, but with abbreviated data as the survex file (from ARGE) is all we have. We already know the survex file. - We already know that it doesn't exist. + We already know that it doesn't exist... though there are bugs.. """ default_note = "This is an ARGE cave where we only have the survex file and no other information" @@ -203,35 +174,31 @@ def do_ARGE_cave(slug, caveid, url, area, svxid): cave = Cave( unofficial_number=caveid.upper(), + kataster_number=caveid.upper(), # should only set this if all digits underground_description="ARGE cave.", survex_file= f"{svxid}.svx", url=url, notes=default_note, + areacode=areacode, ) if cave: cave.save() # must save to have id before foreign keys work. This is also a ManyToMany key. - # cave.area.add(area) - # cave.save() # crashes entire transaction with foreign key error. - # The 'caves' list page uses the area__short_name to select for the area, so these ARGE caves do not appear. - - # message = f" ! {slug:18} ARGE cave url: {url} " - # DataIssue.objects.create(parser="caves", message=message, url=url) - # print(message) try: # Now create a cave slug ID CaveSlug.objects.update_or_create(cave=cave, slug=slug, primary=False) except: - message = f" ! {slug:11s} ARGE CaveSLUG create failure {caveid=} {url=} {area=} {svxid=}" + message = f" ! {slug:11s} ARGE CaveSLUG create failure {caveid=} {url=} {areacode=} {svxid=}" DataIssue.objects.create(parser="caves", message=message) print(message) else: - message = f" ! {slug:11s} ARGE cave create failure {caveid=} {url=} {area=} {svxid=}" + message = f" ! {slug:11s} ARGE cave create failure {caveid=} {url=} {areacode=} {svxid=}" DataIssue.objects.create(parser="caves", message=message) print(message) + return None return cave -def do_pending_cave(slug, caveid, url, area, msg=None): +def do_pending_cave(slug, caveid, url, areacode, msg=None): """ default for a PENDING cave, should be overwritten in the db later if a real cave of the same name exists in expoweb/cave_data/1623-"k".html @@ -250,16 +217,16 @@ def do_pending_cave(slug, caveid, url, area, msg=None): else: id = Path(k) - survex_file = f"caves-{area.short_name}/{id}/{id}.svx" + survex_file = f"caves-{areacode}/{id}/{id}.svx" if Path(settings.SURVEX_DATA, survex_file).is_file(): return survex_file else: - survex_file = f"caves-{area.short_name}/{id}.svx" + survex_file = f"caves-{areacode}/{id}.svx" if Path(settings.SURVEX_DATA, survex_file).is_file(): return survex_file survex_file = "" - d = Path(settings.SURVEX_DATA, f"caves-{area.short_name}/{id}") + d = Path(settings.SURVEX_DATA, f"caves-{areacode}/{id}") if d.is_dir(): prime_suspect = "" dir = d.iterdir() @@ -334,11 +301,10 @@ def do_pending_cave(slug, caveid, url, area, msg=None): survex_file=survex_file, url=url, notes=default_note, + areacode=areacode, ) if cave: cave.save() # must save to have id before foreign keys work. This is also a ManyToMany key. - cave.area.add(area) - cave.save() message = f" ! {slug:18} Pending cave write-up url: {url} - {msg}" DataIssue.objects.create(parser="caves", message=message, url=url) print(message) @@ -555,7 +521,7 @@ def read_cave(filename, cave=None): # print(f"! Entrance {eslug}") if eslug.endswith('a b'): message = f' - Entrance has weird name slug:"{eslug}" cave:"{cave}" caveslug:"{slug}" filename:"cave_data/{filename}"' - DataIssue.objects.create(parser="xEntrances", message=message, url=f"{cave.area}/{cave.area}-{cave.url}_cave_edit/") + DataIssue.objects.create(parser="xEntrances", message=message, url=f"{cave.areacode}/{cave.areacode}-{cave.url}_cave_edit/") # print(message) letter = getXML(e, "letter", maxItems=1, context=context)[0] @@ -566,7 +532,7 @@ def read_cave(filename, cave=None): if letter.lower() not in list(string.ascii_lowercase): letter = "x" message = f"- Warning - Empty 'letter' field for '{eslug}' in multiple-entrance cave '{cave}', setting to {letter}." - DataIssue.objects.create(parser="entrances", message=message, url=f"{cave.area}/{cave.area}-{cave.url}_cave_edit/") + DataIssue.objects.create(parser="entrances", message=message, url=f"{cave.areacode}/{cave.areacode}-{cave.url}_cave_edit/") print(message) if len(entrances) == 1 and not eslug: # may be empty: @@ -584,13 +550,13 @@ def read_cave(filename, cave=None): entrances_xslug[eslug] = entrance except: message = f"! Fail entrance loading {eslug} /entrance_data/{eslug} file does not exist or loading it failed." - DataIssue.objects.create(parser="entrances", message=message, url=f"{cave.area}/{cave.area}-{cave.url}_cave_edit/") + DataIssue.objects.create(parser="entrances", message=message, url=f"{cave.areacode}/{cave.areacode}-{cave.url}_cave_edit/") print(message) return if eslug != f"{entrance}": message = f"eslug {eslug} using different entrance {entrance} to set CaveAndEntrance" - DataIssue.objects.create(parser="xEntrances", message=message, url=f"{cave.area}/{cave.area}-{cave.url}_cave_edit/") + DataIssue.objects.create(parser="xEntrances", message=message, url=f"{cave.areacode}/{cave.areacode}-{cave.url}_cave_edit/") print(message) try: # this fails if there is not an unambiguous letter set. @@ -728,27 +694,13 @@ def read_cave(filename, cave=None): cave.description_file=description_file[0] cave.url=url[0] - areas = getXML(cavecontents, "area", context=context) - cave.area.clear() # Deletes all links to areas in db + areas = getXML(cavecontents, "area", context=context) # can be multiple tags for area_slug in areas: - if area_slug in areas_xslug: - newArea = areas_xslug[area_slug] + if area_slug in ["1623", "1624", "1626", "1627"]: # ignore sub areas which are in another tag + cave.areacode = area_slug else: - areas_new = Area.objects.filter(short_name=area_slug) - if areas_new: - newArea = areas_new[0] # just the first one we find, but we are going to clean up Areas anyway - else: - # Area not seen before. SHould not happen with manual edit - if manual_edit: - message = f" ! Cave edit failure due to unrecognised Area: {area_slug[0]}, skipping this field edit. " - DataIssue.objects.create(parser="caves", message=message) - print(message) - # super value is highly dodgy - newArea = Area(short_name=area_slug, super=Area.objects.get(short_name="1623")) - newArea.save() - areas_xslug[area_slug] = newArea - cave.area.add(newArea) - + cave.subarea = area_slug + entrances = getXML(cavecontents, "entrance", context=context) do_entrances() # print(f"- {entrances_xslug=}") @@ -834,8 +786,6 @@ def readcaves(): #DataIssue.objects.filter(parser="xEntrances").delete() with transaction.atomic(): - area = get_area("1623") - print(" - Reading Entrances from entrance descriptions xml files") for filename in next(os.walk(ENTRANCEDESCRIPTIONS))[2]: # Should be a better way of getting a list of files read_entrance(filename) @@ -860,19 +810,18 @@ def readcaves(): for k in pending: if k[0:3] == "162": - areanum = k[0:4] + areacode = k[0:4] number = k[5:] - url = f"{areanum}/{k[5:]}.html" # Note we are appending the .htm to allow for offline websites + url = f"{areacode}/{k[5:]}.html" # Note we are appending the .htm to allow for offline websites else: - areanum = "1623" + areacode = "1623" number = k url = f"1623/{k}" - area = get_area(areanum) try: - do_pending_cave(k, number, url, area) + do_pending_cave(k, number, url, areacode) except: - message = f" ! Error. Cannot create pending cave, pending-id:{k} in area {areanum}" + message = f" ! Error. Cannot create pending cave, pending-id:{k} in area {areacode}" DataIssue.objects.create(parser="caves", message=message) print(message) raise diff --git a/parsers/locations.py b/parsers/locations.py index e2190c8..bf786ab 100644 --- a/parsers/locations.py +++ b/parsers/locations.py @@ -57,9 +57,9 @@ class MapLocations(object): print(message) continue # skip this entrance try: - areaName = k.getArea().short_name + areaName = k.areacode except: - message = f" ! Failed to get Area on cave '{k}' linked to Entrance:{ent.name} from:{ent.filename} best:{ent.best_station()}" + message = f" ! Failed to get areacode on cave '{k}' linked to Entrance:{ent.name} from:{ent.filename} best:{ent.best_station()}" stash_data_issue(parser="positions", message=message) print(message) store_data_issues() diff --git a/parsers/survex.py b/parsers/survex.py index 88c1099..96b2e4a 100644 --- a/parsers/survex.py +++ b/parsers/survex.py @@ -2169,7 +2169,7 @@ def FindAndLoadSurvex(): # These exceptions WILL be parsed if the are *included by any file which is not excepted unseensroot = re.sub(r"\.svx$", "", UNSEENS) - excpts = ["surface/terrain", "kataster/kataster-boundaries", "gpx/gpx_publish/essentials", "template", "docs", "deprecated", "subsections", "1623-and-1626-no-schoenberg-hs", "1623-and-1624-and-1626-and-1627", "1623-and-1626",unseensroot] + excpts = ["surface/terrain", "kataster/kataster-boundaries", "gpx/gpx_publish/essentials", "template", "docs", "deprecated", "subsections", "1623-and-1626-no-schoenberg-hs", "1623-and-1624-and-1626-and-1627", "1623-and-1626", "dummy_file", unseensroot] removals = set() for x in unseens: for o in excpts: diff --git a/templates/cave.html b/templates/cave.html index 32387f5..f018ef4 100644 --- a/templates/cave.html +++ b/templates/cave.html @@ -43,9 +43,7 @@ {% for f in survexfiles %} - +
- {% if cave.area.all %} - {{ cave.area.all.0.kat_area }} / - {% endif %} + {{ cave.areacode}} / {% if cave.kataster_number %} {{ cave.kataster_number|safe }} {% if cave.entrancelist %} @@ -200,14 +198,14 @@ New Entrance

Survex File(s)

- All survexfiles for this cave
+ All survexfiles for this cave
{% if cave.survex_file %} Primary survex file for this cave
- Download .3d file caves-{{ cave.area.all.0.kat_area }}/{{cave.kataster_number}}/{{svx3d}}.3d + Download .3d file caves-{{ cave.areacode }}/{{cave.kataster_number}}/{{svx3d}}.3d
cave ID '{{cave.reference}}'
-cave survex path '{{ cave.area.all.0.kat_area }}/{{cave.kataster_number}}' +cave survex path '{{ cave.areacode }}/{{cave.kataster_number}}'
{% endif %} {% endblock content %} diff --git a/templates/survexdir.html b/templates/survexdir.html index 4b4fe11..e6854ef 100644 --- a/templates/survexdir.html +++ b/templates/survexdir.html @@ -12,7 +12,7 @@
CaveCave primaryf.primaryf.path
{{f.cave}}{{f.cave}} {{f.cave.areacode}}{f.cave.subarea}} {{f.cave.survex_file}} {{f.primary}}.svx {{f.path}}.svx