From cdeb2d0a3f258900710fa5d6f604666fd48a1fcf Mon Sep 17 00:00:00 2001 From: Philip Sargent Date: Tue, 12 May 2026 00:21:33 +0100 Subject: [PATCH] Cave html file creation working --- core/views/caves.py | 1 + core/views/new_hole.py | 127 +++++++++++++++++++++++++++++++++++----- templates/new_hole.html | 6 +- 3 files changed, 117 insertions(+), 17 deletions(-) diff --git a/core/views/caves.py b/core/views/caves.py index 993519c4..6d2d32a3 100644 --- a/core/views/caves.py +++ b/core/views/caves.py @@ -639,6 +639,7 @@ def edit_cave(request, path="", slug=None): if not cave.url: cave.url = cave.areacode + "/" + cave.number() cave.save() + # save_m2m is Django https://docs.djangoproject.com/en/6.0/topics/forms/modelforms/ form.save_m2m() # this does the many-to-many relationship saving between caves and entrances if slug is None: # it is not visible on the form so it always will be None diff --git a/core/views/new_hole.py b/core/views/new_hole.py index b368421b..fad910db 100644 --- a/core/views/new_hole.py +++ b/core/views/new_hole.py @@ -1,11 +1,13 @@ import re import subprocess +from pathlib import Path from django import forms from django.core.exceptions import ValidationError from django.utils.safestring import mark_safe from django.conf import settings +from troggle.core.models.caves import Cave, CaveAndEntrance, Entrance, GetCaveLookup from troggle.parsers.people import who_is_this from troggle.core.utils import ( get_cookie_max_age, @@ -19,6 +21,8 @@ from troggle.core.utils import ( is_identified_user, write_and_commit, ) +# TO DO check if wallet already exists and if so put a blue label against it & check names are same people +# assuming this is a new wallet for now - so add a check for this? from troggle.core.position_utils import which_area # file-type import, not module type. @@ -196,14 +200,19 @@ class NewHoleForm(forms.Form): # cleaned_data['cameramen_ids'] = cameramen gps_lat = cleaned_data.get("gps_lat") - gps_lang = cleaned_data.get("gps_long") - valid_area, area = which_area(lat, long) + gps_long = cleaned_data.get("gps_long") + valid_area, area = which_area(gps_lat, gps_long) if not valid_area: self.add_error('gps_lat', "Not in Area 1626 or 1623") self.add_error('gps_long', "Not in Area 1626 or 1623") else: - if Cave.objects.filter(unofficial_number=cave_id, areacode=areacode).exists(): - self.add_error('cave_id', "This Cave already exists, pick another identifier.") + if Cave.objects.filter(unofficial_number=cave_id, areacode=area).exists(): + slug = f"{area}-{cave_id}" + error_html = mark_safe( + f"This Cave already exists, pick another identifier, or edit it here: " + f"{slug}" + ) + self.add_error('cave_id', error_html) # Entrance Photo Logic photo_ent_on_camera = cleaned_data.get("photo_ent_on_camera") @@ -334,7 +343,7 @@ def new_hole(request): lat = float(form.data['gps_lat']) long = float(form.data['gps_long']) valid_area, area = which_area(lat, long) - if valid: + if valid_area: areatext = f"in {area}" else: areatext = "Not in 1623 or 1626" @@ -397,9 +406,9 @@ def process_new_hole(form, area): ✅ Create a fixed point *fix record by inserting into :loser:/fixedpts/gps/auto.svx ✅ Do a git commit (loser) of the new GPS position - ⚡Create a new Cave description file + ✅Create a new Cave description file ⚡Create an associated new Entrance description file with GPS location using *fix - ⚡Update the database with this new Cave + ✅Update the database with this new Cave ⚡Update the database with this new Entrance ⚡Do a git commit (expoweb) of the new Cave and Entrance description files ⚡+ Link page to go to @@ -423,8 +432,8 @@ def process_new_hole(form, area): editor = git_string(form.cleaned_data["who_are_you"]) _newfix(form, area, editor) + _newent(form, area, editor) # yes, make the Entrance first _newcave(form, area, editor) - _newent(form, area, editor) return def _newfix(form, area, editor): @@ -453,12 +462,102 @@ def _newfix(form, area, editor): except: raise return + +def _newent(form, areacode, editor): + """All a bit over-complicated by the existance of teh combined Entrance & Letter Form and the + CaveAndEntrance class + + Ideally we want to use the validity checks defined on the Form objects to check that this data is valid. + But really this should be done within the form we have just processed which the user has just filled in. + So we won't use the EntranceForm or the EntranceLetterForm, but just duplicate the checks above instead. + + In the parser, the Entrance is created first, then the Cave. But when doing NewCave, the Cave is created + first, then the Entrance. So this code is derived from a bit of both. + """ + slug = f"{areacode}-{form.cleaned_data.get("cave_id")}" # no letter suffix a,b, or c.. + imgpath = Path(areacode) / form.cleaned_data.get("cave_id") + + ent = Entrance.objects.create( # creates object and saves into db + slug=slug, + filename = slug + ".html", + entrance_description="Created when registering a new cave. " + + "Click on 'Edit' to enter the updated data, then 'Submit'.", + marking="?", + ) + + #ce = CaveAndEntrance(cave=cave, entrance=Entrance()) # creates a new Entrance object as well as a new CE object + # + # Add in default text for various fields here, and links to the two Wallets. + # + + + # + # Add in saving Entrance to database and then .html file to filesystem and git + # + -def _newcave(form, area, editor): - # unofficial_number - slug = f"{area}-{form.cleaned_data.get("cave_id")}" - #cave = make_cave(slug) return -def _newent(form, area, editor): - return \ No newline at end of file +def _guess_survex_file(areacode, id): + 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-{areacode}/{id}.svx" + if Path(settings.SURVEX_DATA, survex_file).is_file(): + return survex_file + return "" + +def _newcave(form, areacode, editor): + cave_id = form.cleaned_data.get("cave_id") + slug = f"{areacode}-{cave_id}" + cave = make_cave(slug) + + # Add in default text for various fields here, and links to the two Wallets. + description = f"Created from New Cave Datasheet on {form.cleaned_data.get("discovery_date")} " + f"details in wallet: {form.cleaned_data.get("survey_wallet")} " + if form.cleaned_data.get("surface_wallet"): + description += f"
discovered using old wallet: {form.cleaned_data.get("surface_wallet")} " + default_note = "Created from New Cave Datasheet. " + + wallet = form.cleaned_data.get("survey_wallet") + wallet_url = "/walletedit/{wallet.replace("#",":")}" + references = f"Wallet {wallet}" + + # TO-DO Need to detect if the existence of the survex was ticked but the file was not found, + # but that is probably normal: people will mostly record the Cave first and then do the survex data. + + cave = Cave( + official_name=form.cleaned_data.get("proposed_name"), + underground_description=description, + unofficial_number=cave_id, + survex_file=_guess_survex_file(areacode, cave_id), # possible that they did the survex file already? + url=f"{areacode}/{cave_id}/{cave_id}.html", + notes=default_note, + areacode=areacode, + fully_explored=form.cleaned_data.get("is_explored"), + unexplored= not form.cleaned_data.get("is_explored"), + references=references, + ) + cave.save() + # need a CaveForm f we do it this way, which is a ModelForm. + # form.save_m2m() # this does the many-to-many relationship saving between caves and entrances + # can we do this manually? + try: + cave_file = cave.file_output() + write_and_commit([cave_file], f"Creating new cave {cave}", editor) + # leave other exceptions unhandled so that they bubble up to user interface + except PermissionError: + message = f"CANNOT save this file.\nPERMISSIONS incorrectly set on server for this file {cave.filename}. Ask a nerd to fix this." + return render(request, "errors/generic.html", {"message": message}) + except WriteAndCommitError as e: + message = f"CANNOT git on server for this file {cave.filename}.\n{e}\nEdits may not be committed.\nAsk a nerd to fix this." + return render(request, "errors/generic.html", {"message": e.message}) + except subprocess.SubprocessError as e: + message = f"CANNOT update server for this file {cave.filename}.\n{e}\nEdits may not be committed.\nAsk a nerd to fix this." + return render(request, "errors/generic.html", {"message": message}) + except: + raise + + return + diff --git a/templates/new_hole.html b/templates/new_hole.html index 0a1fcf6c..67aecea2 100644 --- a/templates/new_hole.html +++ b/templates/new_hole.html @@ -126,7 +126,7 @@

- +

@@ -145,8 +145,8 @@
  • If all is correct, will take you to
    - the Entrance edit page for you to upload the photos
    - the GPSlogs upload page to upload your prospecting track
    -- the new Survex page to upload survey data (if any) -- a new Logbook page if you have not already recorded this +- the new Survex page to upload survey data (if any)
    +- a new Logbook page if you have not already recorded this