mirror of
https://expo.survex.com/repositories/troggle/.git
synced 2024-11-27 17:51:53 +00:00
257 lines
12 KiB
Python
257 lines
12 KiB
Python
|
|
import django.forms as forms
|
|
from django.forms import ModelForm
|
|
from django.forms.models import modelformset_factory
|
|
|
|
from troggle.core.models.caves import Cave, CaveAndEntrance, Entrance
|
|
from troggle.core.views.editor_helpers import HTMLarea
|
|
|
|
from django.core.exceptions import ValidationError
|
|
|
|
# from tinymce.widgets import TinyMCE
|
|
import re
|
|
|
|
|
|
"""These are all the class-based Forms used by troggle.
|
|
There are other, simpler, upload forms in view/uploads.py
|
|
|
|
class-based forms are quicker to set up (for Django experts) but
|
|
are more difficult to maintain (or even begin to understand) by non-Django experts.
|
|
|
|
Notes to self, as I try to work out what the hell is going on:
|
|
|
|
Note that HTMLarea invokes a widget which sets a CSS class which calls javascript in
|
|
templates/html_editor_scripts_css.html - which imports jquery and codemirror directly, without
|
|
declaring it anywhere or locally installing it. (!)
|
|
"""
|
|
|
|
todo = """
|
|
"""
|
|
|
|
|
|
class CaveForm(ModelForm):
|
|
"""Only those fields for which we want to override defaults are listed here
|
|
the other fields of the class Cave are present on the form, but use the default presentation style
|
|
"""
|
|
unofficial_number= forms.CharField(required=False,
|
|
label="Unofficial Number used to construct internal identifiers",
|
|
widget=forms.TextInput(
|
|
attrs={"size": "45", "placeholder": "2035-ZB-03"}))
|
|
|
|
official_name = forms.CharField(required=False,
|
|
label="Name:",widget=forms.TextInput(
|
|
attrs={"size": "45", "placeholder": "ideally official name in German, but any name is OK"}))
|
|
|
|
underground_description = forms.CharField(
|
|
required=False,
|
|
widget=HTMLarea(attrs={"height": "80%", "rows": 20, "placeholder": "Enter page content (using HTML)"}),
|
|
)
|
|
explorers = forms.CharField(
|
|
required=False,
|
|
widget=HTMLarea(attrs={"height": "80%", "rows": 20, "placeholder": "Enter page content (using HTML)"}),
|
|
)
|
|
equipment = forms.CharField(
|
|
required=False,
|
|
widget=HTMLarea(attrs={"height": "80%", "rows": 20, "placeholder": "Enter page content (using HTML)"}),
|
|
)
|
|
survey = forms.CharField(
|
|
required=False,
|
|
widget=HTMLarea(attrs={"height": "80%", "rows": 20, "placeholder": "Enter page content (using HTML)"}),
|
|
)
|
|
# survey = forms.CharField(required = False, widget=TinyMCE(attrs={'cols': 80, 'rows': 10}))
|
|
# kataster_status = forms.CharField(required=False,
|
|
# label = "Kataster status, see below",
|
|
# widget=forms.TextInput(attrs={"placeholder": "see example below"})
|
|
# )
|
|
kataster_code = forms.CharField(required=False,
|
|
label = "Kataster code, see below",
|
|
widget=forms.TextInput(attrs={"placeholder": "see example below"})
|
|
)
|
|
# underground_centre_line = forms.CharField(
|
|
# required=False,
|
|
# widget=HTMLarea(attrs={"height": "80%", "rows": 20, "placeholder": "Enter page content (using HTML)"}),
|
|
# )
|
|
notes = forms.CharField(
|
|
required=False,
|
|
label = "Notes, e.g. progress on issuing kataster no.",
|
|
widget=HTMLarea(attrs={"height": "80%", "rows": 20, "placeholder": "Enter page content (using HTML)"}),
|
|
)
|
|
references = forms.CharField(
|
|
required=False,
|
|
widget=HTMLarea(attrs={"height": "80%", "rows": 20, "placeholder": "Enter page content (using HTML)"}),
|
|
)
|
|
description_file = forms.CharField(required=False, label="Path of top-level description file for this cave, when a separate file is used. Otherwise blank.", widget=forms.TextInput(attrs={"size": "45","placeholder": "usually blank"}), help_text="")
|
|
survex_file = forms.CharField(
|
|
required=False, label="Survex file eg. caves-1623/000/000.svx", widget=forms.TextInput(attrs={"size": "45"})
|
|
)
|
|
length = forms.CharField(required=False, label="Length (m)", widget=forms.TextInput(attrs={"placeholder": "usually blank"}))
|
|
depth = forms.CharField(required=False, label="Depth (m)", widget=forms.TextInput(attrs={"placeholder": "usually blank"}))
|
|
extent = forms.CharField(required=False, label="Extent (m)", widget=forms.TextInput(attrs={"placeholder": "usually blank"}))
|
|
subarea = forms.CharField(required=False, label="Subarea", widget=forms.TextInput(attrs={"placeholder": "usually blank, archaic"}))
|
|
|
|
#cave_slug = forms.CharField()
|
|
|
|
class Meta:
|
|
model = Cave
|
|
exclude = ("filename","url", "underground_centre_line", "kataster_status")
|
|
|
|
field_order = ['unofficial_number', 'kataster_number', 'official_name', 'underground_description', 'survey', 'underground_centre_line', 'explorers', 'equipment', 'notes', 'references', 'description_file', 'survex_file', 'areacode', 'length', 'depth', 'extent',
|
|
'kataster_code', 'kataster_status' ]
|
|
|
|
def clean_cave_slug(self):
|
|
if self.cleaned_data["cave_slug"] == "":
|
|
myArea = self.cleaned_data["areacode"]
|
|
if self.data["kataster_number"]:
|
|
cave_slug = f"{myArea}-{self.cleaned_data['kataster_number']}"
|
|
else:
|
|
cave_slug = f"{myArea}-{self.cleaned_data['unofficial_number']}"
|
|
else:
|
|
cave_slug = self.cleaned_data["cave_slug"]
|
|
# Converting a PENDING cave to a real cave by saving this form
|
|
print("EEE", cave_slug.replace("-PENDING-", "-"))
|
|
return cave_slug.replace("-PENDING-", "-")
|
|
|
|
|
|
def clean(self):
|
|
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."]
|
|
)
|
|
# if self.cleaned_data.get("kataster_number") != "" and self.cleaned_data.get("official_name") == "":
|
|
# self._errors["official_name"] = self.error_class(["This field is required when there is a kataster number."])
|
|
# if cleaned_data.get("url") == []:
|
|
# self._errors["url"] = self.error_class(["This field is required."])
|
|
# if cleaned_data.get("url") and cleaned_data.get("url").startswith("/"):
|
|
# self._errors["url"] = self.error_class(["This field cannot start with a /."])
|
|
return cleaned_data
|
|
|
|
|
|
class EntranceForm(ModelForm):
|
|
"""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 presentation style
|
|
"""
|
|
|
|
name = forms.CharField(required=False, widget=forms.TextInput(attrs={"size": "45", "placeholder": "usually leave this blank"}))
|
|
entrance_description = forms.CharField(
|
|
required=False,
|
|
widget=HTMLarea(attrs={"height": "80%", "rows": 20, "placeholder": "Enter text (using HTML)"}),
|
|
)
|
|
explorers = forms.CharField(required=False, widget=forms.TextInput(attrs={"size": "45"}))
|
|
# explorers = forms.CharField(required = False, widget=TinyMCE(attrs={'cols': 80, 'rows': 10}))
|
|
map_description = forms.CharField(
|
|
label="Map (is this used?)",
|
|
required=False,
|
|
widget=HTMLarea(attrs={"height": "80%", "rows": 20, "placeholder": "Enter text (using HTML)"}),
|
|
)
|
|
location_description = forms.CharField(
|
|
label="Location",
|
|
required=False,
|
|
widget=HTMLarea(attrs={"height": "80%", "rows": 20, "placeholder": "Enter text (using HTML)"}),
|
|
)
|
|
lastvisit = forms.CharField(
|
|
required=False, widget=forms.TextInput(attrs={"size": "10"}), label="Last visit date, e.g. 2023-07-11"
|
|
)
|
|
approach = forms.CharField(
|
|
required=False,
|
|
widget=HTMLarea(attrs={"height": "80%", "rows": 20, "placeholder": "Enter text (using HTML)"}),
|
|
)
|
|
underground_description = forms.CharField(
|
|
required=False,
|
|
widget=HTMLarea(attrs={"height": "80%", "rows": 20, "placeholder": "Enter text (using HTML)"}),
|
|
)
|
|
photo = forms.CharField(
|
|
label="Photos (use 'image' button)",
|
|
|
|
required=False,
|
|
widget=HTMLarea(attrs={"height": "80%", "rows": 20, "placeholder": "Use button on right to add HTML link"}),
|
|
)
|
|
marking_comment = forms.CharField(
|
|
label="Marking text",
|
|
required=False,
|
|
widget=HTMLarea(attrs={"height": "80%", "rows": 20, "placeholder": "Enter exact tag text, e.g. 'CUCC 2035 ZB-03'"}),
|
|
)
|
|
findability_description = forms.CharField(
|
|
required=False,
|
|
label="How to find it",
|
|
widget=HTMLarea(attrs={"height": "80%", "rows": 20, "placeholder": "Enter text (using HTML)"}),
|
|
)
|
|
other_description = forms.CharField(
|
|
label="Other comments",
|
|
required=False,
|
|
widget=HTMLarea(attrs={"height": "80%", "rows": 20, "placeholder": "Usually blank"}),
|
|
)
|
|
# bearings = forms.CharField(
|
|
# label="Bearings (obsolete)",
|
|
# required=False,
|
|
# widget=HTMLarea(attrs={"height": "80%", "rows": 20, "placeholder": "Usually blank"}),
|
|
# )
|
|
tag_station = forms.CharField(
|
|
required=False,
|
|
widget=forms.TextInput(attrs={"size": "50","placeholder": "e.g. 1623.t2035-zb-03a"}),
|
|
label="Tag station: Survex station id, e.g. 1623.p2023-aa-01"
|
|
)
|
|
other_station = forms.CharField(
|
|
required=False,
|
|
widget=forms.TextInput(attrs={"size": "50","placeholder": "e.g. 1623.p2035-zb-03c"}),
|
|
label="Other station: Survex station id, e.g. 1623.gps2018-aa-01"
|
|
)
|
|
|
|
lat_wgs84 = forms.CharField(
|
|
required=False, widget=forms.TextInput(attrs={"size": "10","placeholder": "e.g. 47.123456"}),
|
|
label="Latitude (WSG84) - if no other location"
|
|
)
|
|
long_wgs84 = forms.CharField(
|
|
required=False, widget=forms.TextInput(attrs={"size": "10","placeholder": "e.g. 13.123456"}),
|
|
label="Longitude (WSG84) - if no other location"
|
|
)
|
|
alt = forms.CharField(required=False, label="Altitude (m) - from GPS if you have it, but let it settle.")
|
|
# url = forms.CharField(required=False, label="URL [usually blank]", widget=forms.TextInput(attrs={"size": "45"}))
|
|
|
|
field_order = ['name', 'entrance_description', 'explorers', 'map_description', 'location_description', 'lastvisit', 'approach', 'underground_description', 'photo', 'marking_comment', 'findability_description', 'other_description', 'bearings', 'tag_station', 'other_station', 'easting', 'northing', 'lat_wgs84', 'long_wgs84', 'alt']
|
|
|
|
class Meta:
|
|
model = Entrance
|
|
exclude = (
|
|
"cached_primary_slug",
|
|
"filename",
|
|
"slug",
|
|
"bearings"
|
|
)
|
|
|
|
def clean(self):
|
|
# if self.cleaned_data.get("url"): # can remove this as the form does not have a url field any more, which was never used anyway
|
|
# if self.cleaned_data.get("url").startswith("/"):
|
|
# self._errors["url"] = self.error_class(["This field cannot start with a /."])
|
|
return self.cleaned_data
|
|
|
|
|
|
# This next line is called from the templates/edit_cave.html template.
|
|
# This is sufficient to create an entire entry for for the cave fields automatically
|
|
# http://localhost:8000/cave/new/
|
|
# using django built-in Deep Magic. https://docs.djangoproject.com/en/dev/topics/forms/modelforms/
|
|
# for forms which map directly onto a Django Model
|
|
CaveAndEntranceFormSet = modelformset_factory(CaveAndEntrance, exclude=("cave",))
|
|
# This is used only in edit_entrance() in views/caves.py
|
|
|
|
class EntranceLetterForm(ModelForm):
|
|
"""Form to link entrances to caves, along with an entrance number.
|
|
|
|
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.
|
|
"""
|
|
|
|
# This only needs to be required=True for the second and subsequent entrances, not the first. Tricky.
|
|
entranceletter = forms.CharField(required=False, widget=forms.TextInput(attrs={"size": "2"}))
|
|
|
|
class Meta:
|
|
model = CaveAndEntrance
|
|
exclude = ("cave", "entrance")
|
|
|
|
def full_clean(self):
|
|
super(EntranceLetterForm, self).full_clean()
|
|
try:
|
|
self.instance.validate_unique()
|
|
except forms.ValidationError as e:
|
|
self._update_errors(e)
|