diff --git a/core/forms.py b/core/forms.py index e2124f1..d1156cb 100644 --- a/core/forms.py +++ b/core/forms.py @@ -105,7 +105,7 @@ class CaveForm(ModelForm): def clean(self): - cleaned_data = super(CaveForm, self).clean() + cleaned_data = super(CaveForm, self).clean() # where is this code hidden? How does this work?? if self.data.get("kataster_number") == "" and self.data.get("unofficial_number") == "": self._errors["unofficial_number"] = self.error_class( ["Either the kataster or unoffical number is required."] @@ -226,6 +226,7 @@ class EntranceLetterForm(ModelForm): Nb. The relationship between caves and entrances has historically been a many to many relationship. With entrances gaining new caves and letters when caves are joined. """ + entranceletter = forms.CharField(required=False, widget=forms.TextInput(attrs={"size": "2"})) class Meta: model = CaveAndEntrance diff --git a/core/models/caves.py b/core/models/caves.py index 0cfdd8e..4d268e5 100644 --- a/core/models/caves.py +++ b/core/models/caves.py @@ -64,20 +64,21 @@ class CaveAndEntrance(models.Model): entrances in one form. CASCADE means that if the cave or the entrance is deleted, then this CaveAndEntrance is deleted too + NOT NEEDED anymore if we insist that cave:entrances have 1:n multiplicity. """ cave = models.ForeignKey("Cave", on_delete=models.CASCADE) entrance = models.ForeignKey("Entrance", on_delete=models.CASCADE) - entrance_letter = models.CharField(max_length=20, blank=True, null=True) + entranceletter = models.CharField(max_length=20, blank=True, null=True) class Meta: - unique_together = [["cave", "entrance"], ["cave", "entrance_letter"]] - ordering = ["entrance_letter"] + unique_together = [["cave", "entrance"], ["cave", "entranceletter"]] + ordering = ["entranceletter"] def __str__(self): - return str(self.cave) + str(self.entrance_letter) + return str(self.cave) + str(self.entranceletter) # class CaveSlug(models.Model): -# moved to models/logbooks.py to avoid cyclic import problem +# moved to models/logbooks.py to avoid cyclic import problem. No I don't know why either. class Cave(TroggleModel): # too much here perhaps, @@ -208,8 +209,8 @@ class Cave(TroggleModel): rs = [] res = "" for e in CaveAndEntrance.objects.filter(cave=self): - if e.entrance_letter: - rs.append(e.entrance_letter) + if e.entranceletter: + rs.append(e.entranceletter) rs.sort() prevR = "" n = 0 @@ -246,7 +247,9 @@ class Cave(TroggleModel): return def file_output(self): - filepath = Path(os.path.join(settings.CAVEDESCRIPTIONS, self.filename)) + """This produces the content which wll be re-saved as the cave_data html file. + """ + filepath = Path(settings.CAVEDESCRIPTIONS, self.filename) t = loader.get_template("dataformat/cave.xml") now = datetime.now(timezone.utc) @@ -306,7 +309,7 @@ class Entrance(TroggleModel): url = models.CharField(max_length=300, blank=True, null=True) class Meta: - ordering = ["caveandentrance__entrance_letter"] + ordering = ["caveandentrance__entranceletter"] def __str__(self): return str(self.slug) @@ -325,6 +328,26 @@ class Entrance(TroggleModel): else: return None + def singleletter(self): + """Used in template/dataformat/cave.xml to write out a replacement cave_data file + why is this not working? + """ + cavelist = self.cavelist + try: + first = cavelist[0] + ce = CaveAndEntrance.objects.get(entrance=self, cave=first) + except: + # will fail if no caves in cavelist or if the cave isnt in the db + return "Z" + print(f"singleletter() access for first cave in {cavelist=}") + if ce.entranceletter == "": + print(f"### BLANK LETTER") + return "Y" + else: + letter = ce.entranceletter + print(f"### LETTER {letter}") + return letter + def exact_location(self): return self.single(self.exact_station) diff --git a/core/views/caves.py b/core/views/caves.py index 1c07fda..445d6c6 100644 --- a/core/views/caves.py +++ b/core/views/caves.py @@ -442,7 +442,7 @@ def edit_entrance(request, path="", caveslug=None, entslug=None): entrance = None if entslug: - # print(f"{caveslug=} {entslug=} {path=}") + print(f"{caveslug=} {entslug=} {path=}") caveAndEntrance = CaveAndEntrance.objects.get(entrance=entrance, cave=cave) entlettereditable = False else: @@ -450,15 +450,17 @@ def edit_entrance(request, path="", caveslug=None, entslug=None): entlettereditable = True if request.POST: + print(f"Online edit of entrance {entrance.slug}") form = EntranceForm(request.POST, instance=entrance) entletter = EntranceLetterForm(request.POST, instance=caveAndEntrance) if form.is_valid() and entletter.is_valid(): entrance = form.save(commit=False) - entrance_letter = entletter.save(commit=False) - # print(f"- POST {caveslug=} {entslug=} {path=}") + entranceletter = entletter.save(commit=False) + print(f"- POST {caveslug=} {entslug=} {entranceletter=} {entletter.cleaned_data['entranceletter']=} {path=}") if entslug is None: - if entletter.cleaned_data["entrance_letter"]: - slugname = cave.slug() + entletter.cleaned_data["entrance_letter"] + if entletter.cleaned_data["entranceletter"]: + slugname = cave.slug() + entletter.cleaned_data["entranceletter"] + print(f"- POST letter {entletter.cleaned_data['entranceletter']=}") else: slugname = cave.slug() entrance.slug = slugname @@ -469,26 +471,31 @@ def edit_entrance(request, path="", caveslug=None, entslug=None): entrance.cached_primary_slug = entslug entrance.filename = entslug + ".html" entrance.save() - entrance_letter.entrance = entrance - entrance_letter.save() + entranceletter.entrance = entrance + entranceletter.save() entrance_file = entrance.file_output() - # print(f"Online edit of entrance {entrance.slug}") cave_file = cave.file_output() + + print(f"- POST WRITE letter {entranceletter}") write_and_commit([entrance_file, cave_file], f"Online edit of entrance {entrance.slug}") return HttpResponseRedirect("/" + cave.url) else: # GET the page, not POST, or if either of the forms were invalid when POSTed + print(f"ENTRANCE in db: entranceletter = '{caveAndEntrance.entranceletter}'") if entrance: # re-read entrance data from file. filename = str(entrance.slug +".html") - read_entrance(filename, ent=entrance) + ent = read_entrance(filename, ent=entrance) + print(f"ENTRANCE from file: entranceletter = '{caveAndEntrance.entranceletter}'") form = EntranceForm(instance=entrance) if entslug is None: entletter = EntranceLetterForm() + print(f" Getting entletter from EntranceLetterForm") else: - entletter = caveAndEntrance.entrance_letter + entletter = caveAndEntrance.entranceletter + print(f"{entletter=}") else: form = EntranceForm() entletter = EntranceLetterForm() @@ -508,14 +515,14 @@ def edit_entrance(request, path="", caveslug=None, entslug=None): def ent(request, cave_id, ent_letter): cave = Cave.objects.filter(kataster_number=cave_id)[0] - cave_and_ent = CaveAndEntrance.objects.filter(cave=cave).filter(entrance_letter=ent_letter)[0] + cave_and_ent = CaveAndEntrance.objects.filter(cave=cave).filter(entranceletter=ent_letter)[0] return render( request, "entrance.html", { "cave": cave, "entrance": cave_and_ent.entrance, - "letter": cave_and_ent.entrance_letter, + "letter": cave_and_ent.entranceletter, }, ) diff --git a/parsers/caves.py b/parsers/caves.py index 8a746ac..08c336c 100644 --- a/parsers/caves.py +++ b/parsers/caves.py @@ -91,7 +91,7 @@ def set_dummy_entrance(id, slug, cave, msg="DUMMY"): # try: # entrance = dummy_entrance(id, slug, msg="DUMMY") # entrances_xslug[slug] = entrance - # CaveAndEntrance.objects.update_or_create(cave=cave, entrance_letter="", entrance=entrance) + # CaveAndEntrance.objects.update_or_create(cave=cave, entranceletter="", entrance=entrance) # pass # except: # message = f' ! Entrance Dummy setting failure, slug:"{slug}" cave id :"{id}" ' @@ -363,6 +363,7 @@ def validate_station(station): def read_entrance(filename, ent=None): """Reads an entrance description from the .html file. + Runs on initial full import, and also whenever an entrance is edited online. If not called as part of initial import, then the global lists will not be correct but this is OK, a search will find them in the db. @@ -503,7 +504,7 @@ def read_cave(filename, cave=None): 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/") - print(message) + # print(message) letter = getXML(e, "letter", maxItems=1, context=context)[0] @@ -540,7 +541,7 @@ def read_cave(filename, cave=None): try: # this fails if there is not an unambiguous letter set. CaveAndEntrance.objects.update_or_create( - cave=cave, entrance_letter=letter, entrance=entrance + cave=cave, entranceletter=letter, entrance=entrance ) except: print(f"! Entrance setting failure {slug}") @@ -714,7 +715,7 @@ def read_cave(filename, cave=None): if description_file[0]: # if not an empty string message = f' - {slug:12} Note (not an error): complex description filename "{description_file[0]}" inside "cave_data/{filename}"' DataIssue.objects.create(parser="caves ok", message=message, url=f"/{slug}_cave_edit/") - print(message) + # print(message) if not (Path(EXPOWEB) / description_file[0]).is_file(): message = f' ! {slug:12} description filename "{EXPOWEB}/{description_file[0]}" does not refer to a real file' diff --git a/templates/cave.html b/templates/cave.html index a8c0c5e..32387f5 100644 --- a/templates/cave.html +++ b/templates/cave.html @@ -128,13 +128,13 @@
{% if cave.entrances %}
{{ caveandentrance.entrance_letter}} | +{{ caveandentrance.entranceletter}} | {{ caveandentrance.entrance.name|safe }} |