2
0
mirror of https://expo.survex.com/repositories/troggle/.git synced 2024-11-25 08:41:51 +00:00

trying to isolate bug in letter setting on ents

This commit is contained in:
Philip Sargent 2023-08-03 16:11:46 +03:00
parent 0dfe9d94b2
commit e101f4ed2f
8 changed files with 68 additions and 35 deletions

View File

@ -105,7 +105,7 @@ class CaveForm(ModelForm):
def clean(self): 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") == "": if self.data.get("kataster_number") == "" and self.data.get("unofficial_number") == "":
self._errors["unofficial_number"] = self.error_class( self._errors["unofficial_number"] = self.error_class(
["Either the kataster or unoffical number is required."] ["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. 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. With entrances gaining new caves and letters when caves are joined.
""" """
entranceletter = forms.CharField(required=False, widget=forms.TextInput(attrs={"size": "2"}))
class Meta: class Meta:
model = CaveAndEntrance model = CaveAndEntrance

View File

@ -64,20 +64,21 @@ class CaveAndEntrance(models.Model):
entrances in one form. entrances in one form.
CASCADE means that if the cave or the entrance is deleted, then this CaveAndEntrance CASCADE means that if the cave or the entrance is deleted, then this CaveAndEntrance
is deleted too is deleted too
NOT NEEDED anymore if we insist that cave:entrances have 1:n multiplicity.
""" """
cave = models.ForeignKey("Cave", on_delete=models.CASCADE) cave = models.ForeignKey("Cave", on_delete=models.CASCADE)
entrance = models.ForeignKey("Entrance", 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: class Meta:
unique_together = [["cave", "entrance"], ["cave", "entrance_letter"]] unique_together = [["cave", "entrance"], ["cave", "entranceletter"]]
ordering = ["entrance_letter"] ordering = ["entranceletter"]
def __str__(self): def __str__(self):
return str(self.cave) + str(self.entrance_letter) return str(self.cave) + str(self.entranceletter)
# class CaveSlug(models.Model): # 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): class Cave(TroggleModel):
# too much here perhaps, # too much here perhaps,
@ -208,8 +209,8 @@ class Cave(TroggleModel):
rs = [] rs = []
res = "" res = ""
for e in CaveAndEntrance.objects.filter(cave=self): for e in CaveAndEntrance.objects.filter(cave=self):
if e.entrance_letter: if e.entranceletter:
rs.append(e.entrance_letter) rs.append(e.entranceletter)
rs.sort() rs.sort()
prevR = "" prevR = ""
n = 0 n = 0
@ -246,7 +247,9 @@ class Cave(TroggleModel):
return return
def file_output(self): 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") t = loader.get_template("dataformat/cave.xml")
now = datetime.now(timezone.utc) now = datetime.now(timezone.utc)
@ -306,7 +309,7 @@ class Entrance(TroggleModel):
url = models.CharField(max_length=300, blank=True, null=True) url = models.CharField(max_length=300, blank=True, null=True)
class Meta: class Meta:
ordering = ["caveandentrance__entrance_letter"] ordering = ["caveandentrance__entranceletter"]
def __str__(self): def __str__(self):
return str(self.slug) return str(self.slug)
@ -325,6 +328,26 @@ class Entrance(TroggleModel):
else: else:
return None 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): def exact_location(self):
return self.single(self.exact_station) return self.single(self.exact_station)

View File

@ -442,7 +442,7 @@ def edit_entrance(request, path="", caveslug=None, entslug=None):
entrance = None entrance = None
if entslug: if entslug:
# print(f"{caveslug=} {entslug=} {path=}") print(f"{caveslug=} {entslug=} {path=}")
caveAndEntrance = CaveAndEntrance.objects.get(entrance=entrance, cave=cave) caveAndEntrance = CaveAndEntrance.objects.get(entrance=entrance, cave=cave)
entlettereditable = False entlettereditable = False
else: else:
@ -450,15 +450,17 @@ def edit_entrance(request, path="", caveslug=None, entslug=None):
entlettereditable = True entlettereditable = True
if request.POST: if request.POST:
print(f"Online edit of entrance {entrance.slug}")
form = EntranceForm(request.POST, instance=entrance) form = EntranceForm(request.POST, instance=entrance)
entletter = EntranceLetterForm(request.POST, instance=caveAndEntrance) entletter = EntranceLetterForm(request.POST, instance=caveAndEntrance)
if form.is_valid() and entletter.is_valid(): if form.is_valid() and entletter.is_valid():
entrance = form.save(commit=False) entrance = form.save(commit=False)
entrance_letter = entletter.save(commit=False) entranceletter = entletter.save(commit=False)
# print(f"- POST {caveslug=} {entslug=} {path=}") print(f"- POST {caveslug=} {entslug=} {entranceletter=} {entletter.cleaned_data['entranceletter']=} {path=}")
if entslug is None: if entslug is None:
if entletter.cleaned_data["entrance_letter"]: if entletter.cleaned_data["entranceletter"]:
slugname = cave.slug() + entletter.cleaned_data["entrance_letter"] slugname = cave.slug() + entletter.cleaned_data["entranceletter"]
print(f"- POST letter {entletter.cleaned_data['entranceletter']=}")
else: else:
slugname = cave.slug() slugname = cave.slug()
entrance.slug = slugname entrance.slug = slugname
@ -469,26 +471,31 @@ def edit_entrance(request, path="", caveslug=None, entslug=None):
entrance.cached_primary_slug = entslug entrance.cached_primary_slug = entslug
entrance.filename = entslug + ".html" entrance.filename = entslug + ".html"
entrance.save() entrance.save()
entrance_letter.entrance = entrance entranceletter.entrance = entrance
entrance_letter.save() entranceletter.save()
entrance_file = entrance.file_output() entrance_file = entrance.file_output()
# print(f"Online edit of entrance {entrance.slug}")
cave_file = cave.file_output() 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}") write_and_commit([entrance_file, cave_file], f"Online edit of entrance {entrance.slug}")
return HttpResponseRedirect("/" + cave.url) return HttpResponseRedirect("/" + cave.url)
else: # GET the page, not POST, or if either of the forms were invalid when POSTed 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: if entrance:
# re-read entrance data from file. # re-read entrance data from file.
filename = str(entrance.slug +".html") 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) form = EntranceForm(instance=entrance)
if entslug is None: if entslug is None:
entletter = EntranceLetterForm() entletter = EntranceLetterForm()
print(f" Getting entletter from EntranceLetterForm")
else: else:
entletter = caveAndEntrance.entrance_letter entletter = caveAndEntrance.entranceletter
print(f"{entletter=}")
else: else:
form = EntranceForm() form = EntranceForm()
entletter = EntranceLetterForm() entletter = EntranceLetterForm()
@ -508,14 +515,14 @@ def edit_entrance(request, path="", caveslug=None, entslug=None):
def ent(request, cave_id, ent_letter): def ent(request, cave_id, ent_letter):
cave = Cave.objects.filter(kataster_number=cave_id)[0] 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( return render(
request, request,
"entrance.html", "entrance.html",
{ {
"cave": cave, "cave": cave,
"entrance": cave_and_ent.entrance, "entrance": cave_and_ent.entrance,
"letter": cave_and_ent.entrance_letter, "letter": cave_and_ent.entranceletter,
}, },
) )

View File

@ -91,7 +91,7 @@ def set_dummy_entrance(id, slug, cave, msg="DUMMY"):
# try: # try:
# entrance = dummy_entrance(id, slug, msg="DUMMY") # entrance = dummy_entrance(id, slug, msg="DUMMY")
# entrances_xslug[slug] = entrance # 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 # pass
# except: # except:
# message = f' ! Entrance Dummy setting failure, slug:"{slug}" cave id :"{id}" ' # 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): def read_entrance(filename, ent=None):
"""Reads an entrance description from the .html file. """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 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. 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'): if eslug.endswith('a b'):
message = f' - Entrance has weird name slug:"{eslug}" cave:"{cave}" caveslug:"{slug}" filename:"cave_data/{filename}"' 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/") 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] letter = getXML(e, "letter", maxItems=1, context=context)[0]
@ -540,7 +541,7 @@ def read_cave(filename, cave=None):
try: try:
# this fails if there is not an unambiguous letter set. # this fails if there is not an unambiguous letter set.
CaveAndEntrance.objects.update_or_create( CaveAndEntrance.objects.update_or_create(
cave=cave, entrance_letter=letter, entrance=entrance cave=cave, entranceletter=letter, entrance=entrance
) )
except: except:
print(f"! Entrance setting failure {slug}") 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 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}"' 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/") 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(): 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' message = f' ! {slug:12} description filename "{EXPOWEB}/{description_file[0]}" does not refer to a real file'

View File

@ -128,13 +128,13 @@
<div id="entrances"> <div id="entrances">
<p>{% if cave.entrances %} <p>{% if cave.entrances %}
<h2>Entrances</h2> <h2>Entrances</h2>
<ul> <ol>
{% for ent in cave.entrances %} {% for ent in cave.entrances %}
<li> <li>
{{ ent.entrance_letter|safe }} Id letter: '{{ ent.entranceletter|safe}}'
{% if ent.entrance.name %} {% if ent.entrance.name %}
{{ ent.entrance.name|safe }} {{ ent.entrance.name|safe }}
{% endif %}<a class="editlink" href="{% if local %}https://expo.survex.com{% endif %}{% url "editentrance" ent.entrance.url_parent cave.slug ent.entrance.slug %}">Edit</a> {% endif %}<a class="editlink" href="{% if local %}https://expo.survex.com{% endif %}{% url "editentrance" ent.entrance.url_parent cave.slug ent.entrance.slug %}">Edit this entrance</a>
<dl> <dl>
{% if ent.entrance.marking %} {% if ent.entrance.marking %}
<dt>Marking</dt><dd>{{ ent.entrance.marking_val|safe }}</dd> <dt>Marking</dt><dd>{{ ent.entrance.marking_val|safe }}</dd>
@ -164,7 +164,7 @@
<dt>Underground</dt><dd>{{ ent.entrance.underground_description|safe }}</dd> <dt>Underground</dt><dd>{{ ent.entrance.underground_description|safe }}</dd>
{% endif %} {% endif %}
{% if ent.entrance.photo %} {% if ent.entrance.photo %}
<dt>Photo</dt><dd>{{ ent.entrance.photo|safe }}</dd> <dt>Photo(s)</dt><dd>{{ ent.entrance.photo|safe }}</dd>
{% endif %} {% endif %}
{% if ent.entrance.entrance_description %} {% if ent.entrance.entrance_description %}
<dt>Description</dt><dd>{{ ent.entrance.entrance_description|safe }}</dd> <dt>Description</dt><dd>{{ ent.entrance.entrance_description|safe }}</dd>
@ -173,7 +173,7 @@
<dt>Explorers</dt><dd>{{ ent.entrance.explorers|safe }}</dd> <dt>Explorers</dt><dd>{{ ent.entrance.explorers|safe }}</dd>
{% endif %} {% endif %}
{% if ent.entrance.northing %} {% if ent.entrance.northing %}
<dt>Location</dt><dd>?BMN? Northing: {{ ent.entrance.northing|safe }}, Easting: {{ ent.entrance.easting|safe }}, {{ ent.entrance.alt|safe }}m</dd> <dt>Location</dt><dd>UTM33 Northing: {{ ent.entrance.northing|safe }}, Easting: {{ ent.entrance.easting|safe }}, {{ ent.entrance.alt|safe }}m</dd>
{% endif %} {% endif %}
{% if ent.entrance.tag_station %} {% if ent.entrance.tag_station %}
<dt>Tag Location</dt><dd>{{ ent.entrance.tag_station }} {{ ent.entrance.tag.latlong.0|floatformat:5 }}N {{ ent.entrance.tag.latlong.1|floatformat:5 }}E (UTM33 {{ ent.entrance.tag.y|floatformat:0 }}, {{ ent.entrance.tag.x|floatformat:0 }}), {{ ent.entrance.tag.z|floatformat:0 }}m</dd> <dt>Tag Location</dt><dd>{{ ent.entrance.tag_station }} {{ ent.entrance.tag.latlong.0|floatformat:5 }}N {{ ent.entrance.tag.latlong.1|floatformat:5 }}E (UTM33 {{ ent.entrance.tag.y|floatformat:0 }}, {{ ent.entrance.tag.x|floatformat:0 }}), {{ ent.entrance.tag.z|floatformat:0 }}m</dd>
@ -194,7 +194,7 @@
</dl> </dl>
</li> </li>
{% endfor %} {% endfor %}
</ul> </ol>
{% endif %}</p> {% endif %}</p>
<a class="editlink" href="{% if local %}https://expo.survex.com{% endif %}{% url "newentrance" cave.url_parent cave.slug %}">New Entrance</a> <a class="editlink" href="{% if local %}https://expo.survex.com{% endif %}{% url "newentrance" cave.url_parent cave.slug %}">New Entrance</a>

View File

@ -40,7 +40,8 @@ code used in the Austrian kataster e.g '1/S +' - https://expo/.survex.com/katast
{% for ce in cave.entrances.all %} {% for ce in cave.entrances.all %}
<entrance> <entrance>
<entranceslug>{{ ce.entrance.slug|default_if_none:""|safe }}</entranceslug><!-- Internal ID to refer to each entrance instance in the entrance files (typically the same as that filename (e.g. 1623-161c). Matches the 'slug' field in the entrance file --> <entranceslug>{{ ce.entrance.slug|default_if_none:""|safe }}</entranceslug><!-- Internal ID to refer to each entrance instance in the entrance files (typically the same as that filename (e.g. 1623-161c). Matches the 'slug' field in the entrance file -->
<letter>{{ ce.entrance_letter|default_if_none:""|safe }}</letter><!--Leave blank for single-entrance cave. If there is more than one entrace then the letter needs to be given. Generally matches the entranceslug ID. --> <!-- DEBUG {{ce.cave}}+{{ce.entrance}} '{{ ce.entrance.singleletter }}' ={{ce.entranceletter}}= -->
<letter>{{ ce.entranceletter|default_if_none:""|safe }}</letter><!--Leave blank for single-entrance cave. If there is more than one entrace then the letter needs to be given. Generally matches the entranceslug ID. -->
</entrance> </entrance>
{% endfor %} {% endfor %}
<explorers>{{ cave.explorers|default_if_none:""|safe }}</explorers><!-- 'CUCC Expo' and year(s) of exploration. To distinguish from caves explored by foreign groups. Individual names can be given too if it was a small cave. --> <explorers>{{ cave.explorers|default_if_none:""|safe }}</explorers><!-- 'CUCC Expo' and year(s) of exploration. To distinguish from caves explored by foreign groups. Individual names can be given too if it was a small cave. -->

View File

@ -1,5 +1,5 @@
{% extends "base.html" %} {% extends "base.html" %}
{% block title %}{{ cave.official_name|safe }} - {{ entrance_letter|safe }}{% endblock %} {% block title %}{{ cave.official_name|safe }} - {{ entranceletter|safe }}{% endblock %}
{% block content %} {% block content %}
<table id="cavepage"> <table id="cavepage">

View File

@ -85,7 +85,7 @@
{% endif %} {% endif %}
{% for caveandentrance in cave.caveandentrance_set.all %} {% for caveandentrance in cave.caveandentrance_set.all %}
<tr{% if cave.ours %} class="ours"{% else %} class="notours"{% endif %}> <tr{% if cave.ours %} class="ours"{% else %} class="notours"{% endif %}>
<td><a href="/{{ cave.url }}">{{ caveandentrance.entrance_letter}}</a></td> <td><a href="/{{ cave.url }}">{{ caveandentrance.entranceletter}}</a></td>
<td>{{ caveandentrance.entrance.name|safe }}</td> <td>{{ caveandentrance.entrance.name|safe }}</td>
<td></td> <td></td>
<td></td> <td></td>