summaryrefslogtreecommitdiffstats
path: root/core/views/caves.py
diff options
context:
space:
mode:
authorPhilip Sargent <philip.sargent@gmail.com>2023-11-07 02:12:57 +0200
committerPhilip Sargent <philip.sargent@gmail.com>2023-11-07 02:12:57 +0200
commit07d9365747abda0e08fc3240219d142e340b6b20 (patch)
tree6c5d3b5fba857536876af5f6324b2c72e62067bb /core/views/caves.py
parentbd0a9332df03952b8d7d7c6e6803b774fd2e2278 (diff)
downloadtroggle-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.py104
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)