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

Cave and Entrance forms tuned to user needs

This commit is contained in:
Philip Sargent 2021-04-14 16:28:30 +01:00
parent 54d98f58f3
commit d8b1d59b12
5 changed files with 104 additions and 58 deletions

View File

@ -16,20 +16,29 @@ Some are not used and need renovating or destroying.
''' '''
class CaveForm(ModelForm): class CaveForm(ModelForm):
underground_description = forms.CharField(required = False, widget=forms.Textarea()) '''Only those fields for which we want to override defaults are listed here
explorers = forms.CharField(required = False, widget=forms.Textarea()) the other fields are present on the form, but use the default presentaiton style
equipment = forms.CharField(required = False, widget=forms.Textarea()) '''
survey = forms.CharField(required = False, widget=forms.Textarea()) official_name = forms.CharField(required = False, widget=forms.TextInput(attrs={'size': '45'}))
kataster_status = forms.CharField(required = False, widget=forms.Textarea()) underground_description = forms.CharField(required = False, widget=forms.Textarea(attrs={'rows':9}))
underground_centre_line = forms.CharField(required = False, widget=forms.Textarea()) explorers = forms.CharField(required = False, widget=forms.Textarea(attrs={'rows':2}))
notes = forms.CharField(required = False, widget=forms.Textarea()) equipment = forms.CharField(required = False, widget=forms.Textarea(attrs={'rows':2}))
references = forms.CharField(required = False, widget=forms.Textarea()) survey = forms.CharField(required = False, widget=forms.Textarea(attrs={'rows':2}))
url = forms.CharField(required = True) #survey = forms.CharField(required = False, widget=TinyMCE(attrs={'cols': 80, 'rows': 10}))
kataster_status = forms.CharField(required = False)
underground_centre_line = forms.CharField(required = False, widget=forms.Textarea(attrs={'rows':2}))
notes = forms.CharField(required = False, widget=forms.Textarea(attrs={'rows':2}))
references = forms.CharField(required = False, widget=forms.Textarea(attrs={'rows':1}))
description_file = forms.CharField(required = False, widget=forms.TextInput(attrs={'size': '45'}))
survex_file = forms.CharField(required = False, label="Survex file [caves-1623/000/000.svx]", widget=forms.TextInput(attrs={'size': '45'}))
url = forms.CharField(required = True, label="URL [1623/000/000]", widget=forms.TextInput(attrs={'size': '45'}))
length = forms.CharField(required = False, label="Length (m)")
depth = forms.CharField(required = False, label="Depth (m)")
extent = forms.CharField(required = False, label="Extent (m)")
class Meta: class Meta:
model = Cave model = Cave
exclude = ("filename",) exclude = ("filename",)
def clean(self): def clean(self):
if self.cleaned_data.get("kataster_number") == "" and self.cleaned_data.get("unofficial_number") == "": if self.cleaned_data.get("kataster_number") == "" and self.cleaned_data.get("unofficial_number") == "":
self._errors["unofficial_number"] = self.error_class(["Either the kataster or unoffical number is required."]) self._errors["unofficial_number"] = self.error_class(["Either the kataster or unoffical number is required."])
@ -38,44 +47,57 @@ class CaveForm(ModelForm):
if self.cleaned_data.get("area") == []: if self.cleaned_data.get("area") == []:
self._errors["area"] = self.error_class(["This field is required."]) self._errors["area"] = self.error_class(["This field is required."])
if self.cleaned_data.get("url") and self.cleaned_data.get("url").startswith("/"): if self.cleaned_data.get("url") and self.cleaned_data.get("url").startswith("/"):
self._errors["url"] = self.error_class(["This field can not start with a /."]) self._errors["url"] = self.error_class(["This field cannot start with a /."])
return self.cleaned_data return self.cleaned_data
class VersionControlCommentForm(forms.Form): class VersionControlCommentForm(forms.Form):
description_of_change = forms.CharField(required = True, widget=forms.Textarea()) '''Was appended to all forms. Not used currently
'''
description_of_change = forms.CharField(required = True, widget=forms.Textarea(attrs={'rows':2}))
class EntranceForm(ModelForm): class EntranceForm(ModelForm):
#underground_description = forms.CharField(required = False, widget=TinyMCE(attrs={'cols': 80, 'rows': 30})) '''Only those fields for which we want to override defaults are listed here
the other fields are present on the form, but use the default presentaiton style
'''
name = forms.CharField(required = False, widget=forms.TextInput(attrs={'size': '45'}))
entrance_description = forms.CharField(required = False, widget=forms.Textarea(attrs={'rows':9}))
explorers = forms.CharField(required = False, widget=forms.TextInput(attrs={'size': '45'}))
#explorers = forms.CharField(required = False, widget=TinyMCE(attrs={'cols': 80, 'rows': 10})) #explorers = forms.CharField(required = False, widget=TinyMCE(attrs={'cols': 80, 'rows': 10}))
#equipment = forms.CharField(required = False, widget=TinyMCE(attrs={'cols': 80, 'rows': 10})) map_description = forms.CharField(required = False, widget=forms.Textarea(attrs={'rows':3}))
#survey = forms.CharField(required = False, widget=TinyMCE(attrs={'cols': 80, 'rows': 10})) location_description = forms.CharField(required = False, widget=forms.Textarea(attrs={'rows':3}))
#kataster_status = forms.CharField(required = False, widget=TinyMCE(attrs={'cols': 80, 'rows': 10})) approach = forms.CharField(required = False, widget=forms.Textarea(attrs={'rows':3}))
#underground_centre_line = forms.CharField(required = False, widget=TinyMCE(attrs={'cols': 80, 'rows': 10})) underground_description = forms.CharField(required = False, widget=forms.Textarea(attrs={'rows':3}))
#notes = forms.CharField(required = False, widget=TinyMCE(attrs={'cols': 80, 'rows': 10})) photo = forms.CharField(required = False, widget=forms.Textarea(attrs={'rows':2}))
#references = forms.CharField(required = False, widget=TinyMCE(attrs={'cols': 80, 'rows': 10})) marking_comment = forms.CharField(required = False, widget=forms.Textarea(attrs={'rows':2}))
other_station = forms.CharField(required=False) # Trying to change this to a single line entry findability_description = forms.CharField(required = False, widget=forms.Textarea(attrs={'rows':2}))
tag_station = forms.CharField(required=False) # Trying to change this to a single line entry other_description = forms.CharField(required = False, widget=forms.Textarea(attrs={'rows':2}))
exact_station = forms.CharField(required=False) # Trying to change this to a single line entry bearings = forms.CharField(required = False, widget=forms.Textarea(attrs={'rows':2}))
northing = forms.CharField(required=False) # Trying to change this to a single line entry other_station = forms.CharField(required=False)
easting = forms.CharField(required=False) # Trying to change this to a single line entry tag_station = forms.CharField(required=False)
alt = forms.CharField(required=False) # Trying to change this to a single line entry exact_station = forms.CharField(required=False)
northing = forms.CharField(required=False)
easting = forms.CharField(required=False)
alt = forms.CharField(required=False, label="Altitude (m)")
url = forms.CharField(required = False, label="URL [usually blank]", widget=forms.TextInput(attrs={'size': '45'}))
class Meta: class Meta:
model = Entrance model = Entrance
exclude = ("cached_primary_slug", "filename",) exclude = ("cached_primary_slug", "filename",)
def clean(self): def clean(self):
if self.cleaned_data.get("url").startswith("/"): if self.cleaned_data.get("url").startswith("/"):
self._errors["url"] = self.error_class(["This field can not start with a /."]) self._errors["url"] = self.error_class(["This field cannot start with a /."])
return self.cleaned_data return self.cleaned_data
# This next is called from the templates/edit_cave2.html template. # This next is called from the templates/edit_cave2.html template.
# This is sufficeint to create an entire entry for for the cave fields automatically # This is sufficeint to create an entire entry for for the cave fields automatically
# http://localhost:8000/cave/new/ # http://localhost:8000/cave/new/
# using django built-in stuff: # using django built-in Deep magic. https://docs.djangoproject.com/en/2.2/topics/forms/modelforms/
CaveAndEntranceFormSet = modelformset_factory(CaveAndEntrance, exclude=('cave',)) CaveAndEntranceFormSet = modelformset_factory(CaveAndEntrance, exclude=('cave',))
class EntranceLetterForm(ModelForm): class EntranceLetterForm(ModelForm):
'''Can't see what this does at all
'''
class Meta: class Meta:
model = CaveAndEntrance model = CaveAndEntrance
exclude = ('cave', 'entrance') exclude = ('cave', 'entrance')
@ -120,7 +142,7 @@ def get_name(pe):
return pe.person.first_name return pe.person.first_name
class UploadFileForm(forms.Form): class UploadFileForm(forms.Form):
"""Only called by views.others.newFile() whhich seems to be only about logbook files. """Only called by views.others.newFile() which seems to be only about logbook files.
""" """
# Because this has EXECUTABLE statements in its signature (the fields) they get # Because this has EXECUTABLE statements in its signature (the fields) they get
# executed when this module is LOADED. Which barfs horribly. # executed when this module is LOADED. Which barfs horribly.

View File

@ -182,16 +182,17 @@ class Cave(TroggleModel):
def writeDataFile(self): def writeDataFile(self):
try: try:
f = open(os.path.join(settings.CAVEDESCRIPTIONS, self.filename), "wb") f = open(os.path.join(settings.CAVEDESCRIPTIONS, self.filename), "w")
except: except:
subprocess.call(settings.FIX_PERMISSIONS) subprocess.call(settings.FIX_PERMISSIONS)
f = open(os.path.join(settings.CAVEDESCRIPTIONS, self.filename), "wb") f = open(os.path.join(settings.CAVEDESCRIPTIONS, self.filename), "w")
t = loader.get_template('dataformat/cave.xml') t = loader.get_template('dataformat/cave.xml')
#c = Context({'cave': self}) #c = Context({'cave': self})
c = dict({'cave': self}) c = dict({'cave': self})
u = t.render(c) u = t.render(c)
u8 = u.encode("utf-8") # u8 = u.encode("utf-8")
f.write(u8) # f.write(u8)
f.write(u)
f.close() f.close()
def getArea(self): def getArea(self):
@ -350,10 +351,11 @@ class Entrance(TroggleModel):
subprocess.call(settings.FIX_PERMISSIONS) subprocess.call(settings.FIX_PERMISSIONS)
f = open(os.path.join(settings.ENTRANCEDESCRIPTIONS, self.filename), "w") f = open(os.path.join(settings.ENTRANCEDESCRIPTIONS, self.filename), "w")
t = loader.get_template('dataformat/entrance.xml') t = loader.get_template('dataformat/entrance.xml')
c = Context({'entrance': self}) c = dict({'entrance': self})
u = t.render(c) u = t.render(c)
u8 = u.encode("utf-8") # u8 = u.encode("utf-8")
f.write(u8) # f.write(u8)
f.write(u)
f.close() f.close()
class LogbookEntry(TroggleModel): class LogbookEntry(TroggleModel):
@ -641,10 +643,10 @@ def GetCaveLookup():
Gcavelookup["2015-mf-06"] = Gcavelookup["288"] Gcavelookup["2015-mf-06"] = Gcavelookup["288"]
Gcavelookup["2016-jb-01"] = Gcavelookup["289"] Gcavelookup["2016-jb-01"] = Gcavelookup["289"]
Gcavelookup["2017-pw-01"] = Gcavelookup["277"] Gcavelookup["2017-pw-01"] = Gcavelookup["277"]
Gcavelookup["2018-dm-07"] = Gcavelookup["359"] Gcavelookup["2018-dm-07"] = Gcavelookup["359"] # NB this is 1626
Gcavelookup["2017_cucc_24"] = Gcavelookup["291"] # note _ not - here Gcavelookup["2017_cucc_24"] = Gcavelookup["291"] # note _ not -
Gcavelookup["2017_cucc_23"] = Gcavelookup["295"] Gcavelookup["2017_cucc_23"] = Gcavelookup["295"] # note _ not -
Gcavelookup["2017_cucc_28"] = Gcavelookup["290"] Gcavelookup["2017_cucc_28"] = Gcavelookup["290"] # note _ not -
Gcavelookup["bs17"] = Gcavelookup["283"] Gcavelookup["bs17"] = Gcavelookup["283"]
Gcavelookup["1976/b11"] = Gcavelookup["198"] Gcavelookup["1976/b11"] = Gcavelookup["198"]
@ -679,12 +681,14 @@ def GetCaveLookup():
Gcavelookup["gsh"] = Gcavelookup["291"] Gcavelookup["gsh"] = Gcavelookup["291"]
Gcavelookup["homecoming"] = Gcavelookup["2018-dm-07"] Gcavelookup["homecoming"] = Gcavelookup["2018-dm-07"]
Gcavelookup["heimkommen"] = Gcavelookup["2018-dm-07"]
Gcavelookup["99ob02"] = Gcavelookup["1999-ob-02"] Gcavelookup["99ob02"] = Gcavelookup["1999-ob-02"]
addmore = {} addmore = {}
for id in Gcavelookup: for id in Gcavelookup:
addmore[id.replace("-","_")] = Gcavelookup[id] addmore[id.replace("-","_")] = Gcavelookup[id]
addmore[id.replace("_","-")] = Gcavelookup[id] addmore[id.replace("_","-")] = Gcavelookup[id]
addmore[id.upper()] = Gcavelookup[id]
Gcavelookup = {**addmore, **Gcavelookup} Gcavelookup = {**addmore, **Gcavelookup}
addmore ={} addmore ={}

View File

@ -152,7 +152,7 @@ def cave3d(request, cave_id=''):
try: try:
cave = getCave(cave_id) cave = getCave(cave_id)
except ObjectDoesNotExist: except ObjectDoesNotExist:
return None return HttpResponseNotFound
except Cave.MultipleObjectsReturned: except Cave.MultipleObjectsReturned:
# But only one might have survex data? So scan and return the first that works. # But only one might have survex data? So scan and return the first that works.
caves = getCaves(cave_id) caves = getCaves(cave_id)
@ -337,7 +337,10 @@ def caveLogbook(request, slug):
def edit_cave(request, slug=None): def edit_cave(request, slug=None):
'''This is the form that edits all the cave data and writes out an XML file in the :expoweb: repo folder '''This is the form that edits all the cave data and writes out an XML file in the :expoweb: repo folder
The format for the file being saved is in templates/dataformat/cave.xml The format for the file being saved is in templates/dataformat/cave.xml
It does save the data into into the database directly, not by parsing the file.
''' '''
message = ""
if slug is not None: if slug is not None:
cave = Cave.objects.get(caveslug__slug = slug) cave = Cave.objects.get(caveslug__slug = slug)
else: else:
@ -346,7 +349,8 @@ def edit_cave(request, slug=None):
form = CaveForm(request.POST, instance=cave) form = CaveForm(request.POST, instance=cave)
ceFormSet = CaveAndEntranceFormSet(request.POST) ceFormSet = CaveAndEntranceFormSet(request.POST)
versionControlForm = VersionControlCommentForm(request.POST) versionControlForm = VersionControlCommentForm(request.POST)
if form.is_valid() and ceFormSet.is_valid() and versionControlForm.is_valid(): if form.is_valid() and ceFormSet.is_valid():
#print(f'! POST is valid. {cave}')
cave = form.save(commit = False) cave = form.save(commit = False)
if slug is None: if slug is None:
for a in form.cleaned_data["area"]: for a in form.cleaned_data["area"]:
@ -367,23 +371,33 @@ def edit_cave(request, slug=None):
ceinsts = ceFormSet.save(commit=False) ceinsts = ceFormSet.save(commit=False)
for ceinst in ceinsts: for ceinst in ceinsts:
ceinst.cave = cave ceinst.cave = cave
ceinst.save() ceinst.save()
cave.writeDataFile() cave.writeDataFile()
return HttpResponseRedirect("/" + cave.url) return HttpResponseRedirect("/" + cave.url)
else:
message = f'! POST data is INVALID {cave}'
print(message)
else: else:
form = CaveForm(instance=cave) form = CaveForm(instance=cave)
ceFormSet = CaveAndEntranceFormSet(queryset=cave.caveandentrance_set.all()) ceFormSet = CaveAndEntranceFormSet(queryset=cave.caveandentrance_set.all())
versionControlForm = VersionControlCommentForm() #versionControlForm = VersionControlCommentForm()
return render(request, return render(request,
'editcave2.html', 'editcave2.html',
{'form': form, {'form': form, 'cave': cave, 'message': message,
'caveAndEntranceFormSet': ceFormSet, 'caveAndEntranceFormSet': ceFormSet,
'versionControlForm': versionControlForm #'versionControlForm': versionControlForm
}) })
@login_required_if_public @login_required_if_public
def editEntrance(request, caveslug, slug=None): def editEntrance(request, caveslug, slug=None):
'''This is the form that edits the entrance data for a single entrance and writes out
an XML file in the :expoweb: repo folder
The format for the file being saved is in templates/dataformat/entrance.xml
It does save the data into into the database directly, not by parsing the file.
'''
message = ""
cave = Cave.objects.get(caveslug__slug = caveslug) cave = Cave.objects.get(caveslug__slug = caveslug)
if slug is not None: if slug is not None:
entrance = Entrance.objects.get(entranceslug__slug = slug) entrance = Entrance.objects.get(entranceslug__slug = slug)
@ -391,12 +405,12 @@ def editEntrance(request, caveslug, slug=None):
entrance = Entrance() entrance = Entrance()
if request.POST: if request.POST:
form = EntranceForm(request.POST, instance = entrance) form = EntranceForm(request.POST, instance = entrance)
versionControlForm = VersionControlCommentForm(request.POST) #versionControlForm = VersionControlCommentForm(request.POST)
if slug is None: if slug is None:
entletter = EntranceLetterForm(request.POST) entletter = EntranceLetterForm(request.POST)
else: else:
entletter = None entletter = None
if form.is_valid() and versionControlForm.is_valid() and (slug is not None or entletter.is_valid()): if form.is_valid() and (slug is not None or entletter.is_valid()):
entrance = form.save(commit = False) entrance = form.save(commit = False)
if slug is None: if slug is None:
slugname = cave.slug() + entletter.cleaned_data["entrance_letter"] slugname = cave.slug() + entletter.cleaned_data["entrance_letter"]
@ -412,17 +426,20 @@ def editEntrance(request, caveslug, slug=None):
el.save() el.save()
entrance.writeDataFile() entrance.writeDataFile()
return HttpResponseRedirect("/" + cave.url) return HttpResponseRedirect("/" + cave.url)
else:
message = f'! POST data is INVALID {cave}'
print(message)
else: else:
form = EntranceForm(instance = entrance) form = EntranceForm(instance = entrance)
versionControlForm = VersionControlCommentForm() #versionControlForm = VersionControlCommentForm()
if slug is None: if slug is None:
entletter = EntranceLetterForm(request.POST) entletter = EntranceLetterForm(request.POST)
else: else:
entletter = None entletter = None
return render(request, return render(request,
'editentrance.html', 'editentrance.html',
{'form': form, {'form': form, 'cave': cave, 'message': message,
'versionControlForm': versionControlForm, #'versionControlForm': versionControlForm,
'entletter': entletter 'entletter': entletter
}) })

View File

@ -1,6 +1,5 @@
{% extends "cavebase.html" %} {% extends "cavebase.html" %}
{% load csrffaker %} {% block title %}Edit Cave - {{cave.official_name|safe}} - {{cave.kataster_number}}{% endblock %}
{% block title %}Edit Cave{% endblock %}
{% block extraheaders %} {% block extraheaders %}
<link rel="stylesheet" href="{{ settings.JSLIB_URL }}jquery-ui/css/lightness/jquery-ui.css" type="text/css" media="all" /> <link rel="stylesheet" href="{{ settings.JSLIB_URL }}jquery-ui/css/lightness/jquery-ui.css" type="text/css" media="all" />
@ -9,7 +8,8 @@
<!--<script src="{{ settings.TINY_MCE_MEDIA_URL }}tiny_mce.js" type="text/javascript"></script>--> <!--<script src="{{ settings.TINY_MCE_MEDIA_URL }}tiny_mce.js" type="text/javascript"></script>-->
{% endblock %} {% endblock %}
{% block content %} {% block content %}
<h1>Edit Cave</h1> <h1>Edit Cave - {{cave.official_name|safe}} - {{cave.kataster_number}}</h1>
<h2>{{message}}</h2>
<form action="" method="post">{% csrf_token %} <form action="" method="post">{% csrf_token %}
<table>{{ form }}{{caveAndEntranceFormSet}}</table> <table>{{ form }}{{caveAndEntranceFormSet}}</table>
{{ versionControlForm }} {{ versionControlForm }}

View File

@ -1,15 +1,18 @@
{% extends "cavebase.html" %} {% extends "cavebase.html" %}
{% load csrffaker %}
{% block title %}Edit Entrance{% endblock %} {% block title %}Edit Entrance{% endblock %}
{% block extraheaders %} {% block extraheaders %}
<link rel="stylesheet" href="{{ settings.JSLIB_URL }}jquery-ui/css/lightness/jquery-ui.css" type="text/css" media="all" /> <link rel="stylesheet" href="{{ settings.JSLIB_URL }}jquery-ui/css/lightness/jquery-ui.css" type="text/css" media="all" />
<script src="{{ settings.JSLIB_URL }}jquery-ui/jquery-ui.min.js" type="text/javascript"></script> <script src="{{ settings.JSLIB_URL }}jquery-ui/jquery-ui.min.js" type="text/javascript"></script>
!--<script src="{{ settings.TINY_MCE_MEDIA_URL }}tiny_mce.js" type="text/javascript"></script>--> <!--<script src="{{ settings.TINY_MCE_MEDIA_URL }}tiny_mce.js" type="text/javascript"></script>-->
{% endblock %} {% endblock %}
{% block content %} {% block content %}
<h1>Edit Entrance - at cave {{cave.official_name|safe}} - {{cave.kataster_number}}</h1>
<h2>{{message}}</h2>
<p>{{entletter}}
<form action="" method="post">{% csrf_token %} <form action="" method="post">{% csrf_token %}
<table>{{entletter}}{{ form }}</table> <table>{{ form }}</table>
{{ versionControlForm }} {{ versionControlForm }}
<p><input type="submit" value="Submit" /></p> <p><input type="submit" value="Submit" /></p>
</form> </form>