2
0
mirror of https://expo.survex.com/repositories/troggle/.git synced 2024-11-24 16:21:53 +00:00
troggle/core/forms.py

233 lines
11 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 by non-Django experts.
"""
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
"""
official_name = forms.CharField(required=False, widget=forms.TextInput(attrs={"size": "45"}))
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)
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,
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"}), help_text="")
survex_file = forms.CharField(
required=False, label="Survex file eg. caves-1623/000/000.svx", widget=forms.TextInput(attrs={"size": "45"})
)
#url = forms.CharField(required=True, label="URL eg. 1623/000/000 (no .html)", 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)")
#cave_slug = forms.CharField()
class Meta:
model = Cave
exclude = ("filename",)
field_order = ['unofficial_number', 'kataster_number', 'official_name', 'underground_description', 'explorers', 'equipment', 'survey', 'kataster_status', 'kataster_code','underground_centre_line', 'notes', 'references', 'description_file', 'survex_file', 'areacode', 'url', 'length', 'depth', 'extent']
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_url(self):
# data = self.cleaned_data["url"]
# if not re.match("\d\d\d\d/.", data):
# raise ValidationError("URL must start with a four digit Kataster area.")
# return data
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"}))
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(
required=False,
widget=HTMLarea(attrs={"height": "80%", "rows": 20, "placeholder": "Enter text (using HTML)"}),
)
location_description = forms.CharField(
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="Date of last visit, 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(
required=False,
widget=HTMLarea(attrs={"height": "80%", "rows": 20, "placeholder": "Enter text (using HTML)"}),
)
marking_comment = forms.CharField(
required=False,
widget=HTMLarea(attrs={"height": "80%", "rows": 20, "placeholder": "Enter text (using HTML)"}),
)
findability_description = forms.CharField(
required=False,
widget=HTMLarea(attrs={"height": "80%", "rows": 20, "placeholder": "Enter text (using HTML)"}),
)
other_description = forms.CharField(
required=False,
widget=HTMLarea(attrs={"height": "80%", "rows": 20, "placeholder": "Enter text (using HTML)"}),
)
bearings = forms.CharField(
required=False,
widget=HTMLarea(attrs={"height": "80%", "rows": 20, "placeholder": "Enter text (using HTML)"}),
)
tag_station = forms.CharField(
required=False,
widget=forms.TextInput(attrs={"size": "50"}), label="Tag station: Survex station id, e.g. 1623.p2023-xx-01"
)
exact_station = forms.CharField(
required=False,
widget=forms.TextInput(attrs={"size": "50"}), label="Exact station: Survex station id, e.g. 1623.2023-xx-01.2"
)
other_station = forms.CharField(
required=False,
widget=forms.TextInput(attrs={"size": "50"}), label="Other station: Survex station id, e.g. 1623.2023-xx-01.33"
)
northing = forms.CharField(
required=False, widget=forms.TextInput(attrs={"size": "10"}), label="Northing (UTM) - from survex data"
)
easting = forms.CharField(
required=False, widget=forms.TextInput(attrs={"size": "10"}), label="Easting (UTM) - from survex data"
)
lat_wgs84 = forms.CharField(
required=False, widget=forms.TextInput(attrs={"size": "10"}), label="Latitude (WSG84) - if no other location"
)
long_wgs84 = forms.CharField(
required=False, widget=forms.TextInput(attrs={"size": "10"}), label="Longitude (WSG84) - if no other location"
)
alt = forms.CharField(required=False, label="Altitude (m)")
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', 'exact_station', 'other_station', 'northing', 'easting', 'lat_wgs84', 'long_wgs84', 'alt', 'url']
class Meta:
model = Entrance
exclude = (
"cached_primary_slug",
"filename",
)
def clean(self):
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.
"""
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)