diff options
author | Philip Sargent <philip.sargent@gmail.com> | 2023-11-07 02:12:57 +0200 |
---|---|---|
committer | Philip Sargent <philip.sargent@gmail.com> | 2023-11-07 02:12:57 +0200 |
commit | 07d9365747abda0e08fc3240219d142e340b6b20 (patch) | |
tree | 6c5d3b5fba857536876af5f6324b2c72e62067bb /core/views/caves.py | |
parent | bd0a9332df03952b8d7d7c6e6803b774fd2e2278 (diff) | |
download | troggle-07d9365747abda0e08fc3240219d142e340b6b20.tar.gz troggle-07d9365747abda0e08fc3240219d142e340b6b20.tar.bz2 troggle-07d9365747abda0e08fc3240219d142e340b6b20.zip |
fixed many problems in creating new entrances
Diffstat (limited to 'core/views/caves.py')
-rw-r--r-- | core/views/caves.py | 104 |
1 files changed, 80 insertions, 24 deletions
diff --git a/core/views/caves.py b/core/views/caves.py index adb3398..9d2512d 100644 --- a/core/views/caves.py +++ b/core/views/caves.py @@ -475,6 +475,30 @@ def edit_entrance(request, path="", caveslug=None, entslug=None): GET RID of all this entranceletter stuff. Far too overcomplexified. We don't need it. Just the entrance slug is fine, then check uniqueness. """ + def check_new_slugname_ok(slug, letter): + """In Nov.2023 it is possible to create a 2nd entrance and not set an entrance letter, + which leads to a constraint uniqueness crash. FIX THIS. + The letter may be set to an existing letter, OR it may be unset, but there may + be an existing unlettered single entrance. Both of these will crash unless fixed. + """ + slugname = f"{slug}{letter}" + nents = Entrance.objects.filter(slug=slugname).count() + print(f"NUM ents {slugname=} => {nents}") + if nents == 0: + # looks good, but we need to check the CaveaAndEntrance object too + e = entrance #Entrance.objects.get(slug=slugname) # does not exist yet! + gcl = GetCaveLookup() + c = gcl[slug] + nce = CaveAndEntrance.objects.filter(cave=c, entrance=e).count() + if nce == 0 : + return slugname, letter + + # That entrance already exists, or the CE does, OK.. do recursive call, starting at "b" + if letter =="": + return check_new_slugname_ok(slug, "b") + else: + nextletter = chr(ord(letter)+1) + return check_new_slugname_ok(slug, nextletter) try: cave = Cave.objects.get(caveslug__slug=caveslug) @@ -495,42 +519,60 @@ def edit_entrance(request, path="", caveslug=None, entslug=None): caveAndEntrance = CaveAndEntrance.objects.get(entrance=entrance, cave=cave) entlettereditable = False else: - caveAndEntrance = CaveAndEntrance(cave=cave, entrance=Entrance()) + caveAndEntrance = CaveAndEntrance(cave=cave, entrance=Entrance()) # creates a new Entrance object as well as a new CE object entlettereditable = True - if caveAndEntrance.entranceletter == "" and cave.entrances().count() > 0 : + ce = caveAndEntrance + if ce.entranceletter == "" and cave.entrances().count() > 0 : # this should not be blank on a multiple-entrance cave # but it doesn't trigger the entrance letter form unless entletter has a value - entlettereditable = True + entlettereditable = True # but the user has to remember to actually set it... print(f"{entlettereditable=}") - # if the entletter is no editable, then the entletterform does not appear and so is always invalid. + # if the entletter is not editable, then the entletterform does not appear and so is always invalid. if request.POST: print(f"POST Online edit of entrance: '{entrance}' where {cave=}") entform = EntranceForm(request.POST, instance=entrance) + if not entlettereditable: - entranceletter = caveAndEntrance.entranceletter - ce = caveAndEntrance + entranceletter = ce.entranceletter else: - entletterform = EntranceLetterForm(request.POST, instance=caveAndEntrance) + entletterform = EntranceLetterForm(request.POST, instance=ce) if entletterform.is_valid(): ce = entletterform.save(commit=False) entranceletter = entletterform.cleaned_data["entranceletter"] + message = f"- POST valid {caveslug=} {entslug=} {path=} entletterform valid \n {entletterform=}." + print(message) else: - print(f"- POST INVALID {caveslug=} {entslug=} {path=} entletterform invalid.") - return render(request, "errors/badslug.html", {"badslug": "entletter problem in edit_entrances()"}) - # if entform.is_valid() and entletterform.is_valid(): - if entform.is_valid(): + # maybe this doesn't matter? It just means entranceletter unset ? + # probably because 'Cave and entrance with this Cave and Entranceletter already exists.' + message = f"- POST INVALID {caveslug=} {entslug=} {path=} entletterform invalid \n{entletterform.errors=}\n{entletterform=}." + print(message) + # if entletterform.errors: + # for field in entletterform: + # for error in field.errors: + # print(f"ERR {field=} {error=}") + # return render(request, "errors/generic.html", {"message": message}) + entranceletter="" + + if not entform.is_valid(): + message = f"- POST INVALID {caveslug=} {entslug=} {path=} entform valid:{entform.is_valid()} entletterform valid:{entletterform.is_valid()}" entrance = entform.save(commit=False) + print(message) + return render(request, "errors/generic.html", {"message": message}) + else: print(f"- POST {caveslug=} {entslug=} {entranceletter=} {path=}") if entslug is None: + # we are creating a new entrance if entranceletter: - slugname = cave.slug() + entranceletter - print(f"- POST letter {entranceletter=}") + slugname, letter = check_new_slugname_ok(cave.slug(), entranceletter) else: - slugname = cave.slug() + 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" @@ -541,41 +583,48 @@ def edit_entrance(request, path="", caveslug=None, entslug=None): try: entrance.save() except: - # fails with uniqueness constraint failure. Which is on CaveAndEntrance, not just on entrance, which is bizarre. + # 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}") 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: + # 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=}") - write_and_commit([entrance_file, cave_file], f"Online edit of entrance {entrance.slug}") - return HttpResponseRedirect("/" + cave.url) - else: # one of the forms is not valid - print(f"- POST INVALID {caveslug=} {entslug=} {path=} entform valid:{entform.is_valid()} entletterform valid:{entletterform.is_valid()}") + if write_and_commit([entrance_file, cave_file], f"Online edit of entrance {entrance.slug}"): + return HttpResponseRedirect("/" + cave.url) + else: + efilepath, econtent, eencoding = entrance_file + cfilepath, ccontent, cencoding = cave_file + message = f"- FAIL write_and_commit \n entr:'{efilepath}'\n cave:'{cfilepath}'" + print(message) + return render(request, "errors/generic.html", {"message": message}) else: # GET the page, not POST, or if either of the forms were invalid when POSTed entletterform = None entletter = "" - print(f"ENTRANCE in db: entranceletter = '{caveAndEntrance.entranceletter}'") + print(f"ENTRANCE in db: entranceletter = '{ce.entranceletter}'") 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 = '{caveAndEntrance.entranceletter}'") + print(f"ENTRANCE from file: entranceletter = '{ce.entranceletter}'") entform = EntranceForm(instance=entrance) if entslug is None: entletterform = EntranceLetterForm() # print(f" Getting entletter from EntranceLetterForm") else: - entletter = caveAndEntrance.entranceletter + entletter = ce.entranceletter if entletter == "": entletterform = EntranceLetterForm() print(f" Blank value: getting entletter from EntranceLetterForm") @@ -619,7 +668,14 @@ def cave_debug(request): {"ents": ents}, ) - +def caveslist(request): + caves = Cave.objects.all() + print("CAVESLIST") + return render( + request, + "caveslist.html", + {"caves": caves}, + ) def get_entrances(request, caveslug): try: cave = Cave.objects.get(caveslug__slug=caveslug) |