From 2215464cfa0ce1fd3f530a43eb3ef30cd7393d29 Mon Sep 17 00:00:00 2001 From: Philip Sargent Date: Wed, 8 Nov 2023 02:12:37 +0200 Subject: [PATCH] fix error on first creating new ent --- core/models/caves.py | 6 +++--- core/utils.py | 24 ++++++++++++++++++------ core/views/caves.py | 28 +++++++++++++++++++--------- media/jslib/readme.txt | 1 + 4 files changed, 41 insertions(+), 18 deletions(-) diff --git a/core/models/caves.py b/core/models/caves.py index 1c9eaf7..fe22ea8 100644 --- a/core/models/caves.py +++ b/core/models/caves.py @@ -237,14 +237,14 @@ class Entrance(TroggleModel): entrance_description = models.TextField(blank=True, null=True) explorers = models.TextField(blank=True, null=True) filename = models.CharField(max_length=200) - findability = models.CharField(max_length=1, choices=FINDABLE_CHOICES, blank=True, null=True) + findability = models.CharField(max_length=1, choices=FINDABLE_CHOICES, blank=True, null=True, default="?") findability_description = models.TextField(blank=True, null=True) lastvisit = models.TextField(blank=True, null=True) lat_wgs84 = models.TextField(blank=True, null=True) # manually entered not calculated location_description = models.TextField(blank=True, null=True) long_wgs84 = models.TextField(blank=True, null=True) # manually entered not calculated map_description = models.TextField(blank=True, null=True) - marking = models.CharField(max_length=2, choices=MARKING_CHOICES) + marking = models.CharField(max_length=2, choices=MARKING_CHOICES, default="?") marking_comment = models.TextField(blank=True, null=True) name = models.CharField(max_length=100, blank=True, null=True) other_description = models.TextField(blank=True, null=True) @@ -386,7 +386,7 @@ class Entrance(TroggleModel): if not self.filename: self.filename = self.slug + ".html" self.save() - filepath = Path(os.path.join(settings.ENTRANCEDESCRIPTIONS, self.filename)) + filepath = self.get_file_path() t = loader.get_template("dataformat/entrance.xml") now = datetime.now(timezone.utc) diff --git a/core/utils.py b/core/utils.py index 7111c0c..5d2d262 100644 --- a/core/utils.py +++ b/core/utils.py @@ -138,8 +138,6 @@ nothing to commit, working tree clean def write_and_commit(files, message): """Writes the content to the filepath and adds and commits the file to git. If this fails, a WriteAndCommitError is raised. - This does not create any needed intermediate folders, which is what we do when writing survex files, so functionality here - is duplicated in only_commit() These need refactoring """ @@ -153,7 +151,10 @@ def write_and_commit(files, message): # GIT see also core/views/expo.py editexpopage() os.makedirs(os.path.dirname(filepath), exist_ok = True) if filepath.is_dir(): - return False + raise WriteAndCommitError( + f"CANNOT write this file {filepath} as this is an existing DIRECTORY." + ) + #return False if encoding: mode = "w" kwargs = {"encoding": encoding} @@ -164,10 +165,14 @@ def write_and_commit(files, message): with open(filepath, mode, **kwargs) as f: print(f"WRITING {cwd}/{filename} ") f.write(content) - except PermissionError: + except PermissionError as e: raise WriteAndCommitError( - f"CANNOT save this file.\nPERMISSIONS incorrectly set on server for this file {filename}. Ask a nerd to fix this." + f"CANNOT save this file.\nPERMISSIONS incorrectly set on server for this file {filepath}. Ask a nerd to fix this: {e}" ) + except Exception as e: + raise WriteAndCommitError( + f"CANNOT write this file {filepath}. Ask a nerd to fix this: {e}" + ) cmd_diff = [git, "diff", filename] cp_diff = subprocess.run(cmd_diff, cwd=cwd, capture_output=True, text=True) commands.append(cmd_diff) @@ -242,7 +247,10 @@ class WriteAndCommitError(Exception): def writetrogglefile(filepath, filecontent): - """Commit the new saved file to git + """ + REPLACE with call to write_and_commit + any necessary setup + + Commit the new saved file to git Callers to cave.writeDataFile() or entrance.writeDataFile() should handle the exception PermissionsError explicitly """ # GIT see also core/views/expo.py editexpopage() @@ -301,6 +309,10 @@ def height_from_utm(easting, northing): def find_nearest_point(points, target_point): """Returns the nearest point to a target point from a list of points. + TODO FIND OUT + 1. is this SRTM data ? + 2. what is the zero altitude datum? Geoid or ellisoid ? Do we need to subtract 47m ?? + In our dataset, the survey stations are all within 30m of an srtm reference point. So we can safely ignore points more than 100m away in either x or y directions. diff --git a/core/views/caves.py b/core/views/caves.py index 5ac3725..3884a1a 100644 --- a/core/views/caves.py +++ b/core/views/caves.py @@ -561,46 +561,52 @@ def edit_entrance(request, path="", caveslug=None, entslug=None): print(f"- POST {caveslug=} {entslug=} {entranceletter=} {path=}") if entslug is None: # we are creating a new entrance + entrance = entform.save(commit=False) + # entrance = ce.entrance # the one we created earlier? + if entranceletter: slugname, letter = check_new_slugname_ok(cave.slug(), entranceletter) else: slugname, letter = check_new_slugname_ok(cave.slug(), "") ce.entranceletter = letter - entrance = ce.entrance # the one we created earlier entrance.slug = slugname entrance.cached_primary_slug = slugname entrance.filename = slugname + ".html" else: + # an existing entrance ? entrance.slug = entslug entrance.cached_primary_slug = entslug entrance.filename = entslug + ".html" try: entrance.save() - except: + print(f"- post {entrance.slug=} {entrance.tag_station=} {entrance.other_station=}") + except Exception as e: # fails with uniqueness constraint failure. Which is on CaveAndEntrance, not just on entrance, # which is confusing to a user who is just editing an Entrance. # Can happen when user specifies an existing letter! (or none, when they should set one) print(f"SAVE EXCEPTION FAIL {entrance=}") - print(f"CAVE {cave}") + print(f"CAVE {cave}\n{e}") for ce in cave.entrances(): print(f"CAVE:{ce.cave} - ENT:{ce.entrance} - LETTER:'{ce.entranceletter}'") raise ce.entrance = entrance - # try not to do this: + # try not to invoke this: # UNIQUE constraint failed: core_caveandentrance.cave_id, core_caveandentrance.entranceletter ce.save() entrance_file = entrance.file_output() cave_file = cave.file_output() + print(f"- POST WRITE letter: '{ce}' {entrance=}") - if write_and_commit([entrance_file, cave_file], f"Online edit of entrance {entrance.slug}"): + try: + write_and_commit([entrance_file, cave_file], f"Online edit of entrance {entrance.slug}") return HttpResponseRedirect("/" + cave.url) - else: + except Exception as e: efilepath, econtent, eencoding = entrance_file cfilepath, ccontent, cencoding = cave_file - message = f"- FAIL write_and_commit \n entr:'{efilepath}'\n cave:'{cfilepath}'" + message = f"- FAIL write_and_commit \n entr:'{efilepath}'\n cave:'{cfilepath}'\n\n{e}" print(message) return render(request, "errors/generic.html", {"message": message}) @@ -611,8 +617,12 @@ def edit_entrance(request, path="", caveslug=None, entslug=None): if entrance: # re-read entrance data from file. filename = str(entrance.slug +".html") - ent = read_entrance(filename, ent=entrance) - print(f"ENTRANCE from file: entranceletter = '{ce.entranceletter}'") + try: + ent = read_entrance(filename, ent=entrance) + print(f"ENTRANCE from file: entranceletter = '{ce.entranceletter}'") + except: + # ent only in db not on file. Interesting, let's run with it using whatever we have in the db + print(f"ENTRANCE NOT read from file: entranceletter = '{ce.entranceletter}'") entform = EntranceForm(instance=entrance) if entslug is None: diff --git a/media/jslib/readme.txt b/media/jslib/readme.txt index 68acd3b..cc5f361 100644 --- a/media/jslib/readme.txt +++ b/media/jslib/readme.txt @@ -20,6 +20,7 @@ class TroggleModelAdmin(admin.ModelAdmin): NB any *Admin class is used in the Django control panel only. The jquery links have been REMOVED from the templates as they were not used anywhere. + templates/editentrance.html: {% extends "cavebase.html" %}