2020-05-28 04:54:53 +01:00
2011-07-11 02:10:22 +01:00
import django . forms as forms
2020-05-28 04:54:53 +01:00
from django . forms import ModelForm
2012-06-10 14:59:21 +01:00
from django . forms . models import modelformset_factory
2023-01-19 18:35:56 +00:00
2023-01-29 16:47:46 +00:00
from troggle . core . models . caves import Cave , CaveAndEntrance , Entrance
2023-01-19 18:35:56 +00:00
from troggle . core . views . editor_helpers import HTMLarea
2020-05-28 04:54:53 +01:00
2023-04-30 19:00:22 +01:00
from django . core . exceptions import ValidationError
2023-01-30 19:04:36 +00:00
# from tinymce.widgets import TinyMCE
2023-04-30 19:00:22 +01:00
import re
2011-07-11 02:10:22 +01:00
2020-05-28 04:54:53 +01:00
2023-01-30 19:04:36 +00:00
""" These are all the class-based Forms used by troggle.
2022-03-22 02:22:15 +00:00
There are other , simpler , upload forms in view / uploads . py
2023-07-31 13:49:54 +01:00
class - based forms are quicker to set up ( for Django experts ) but
2023-11-02 19:05:08 +00:00
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 . ( ! )
2023-01-30 19:04:36 +00:00
"""
todo = """
"""
2021-04-13 01:37:42 +01:00
2021-04-21 19:08:42 +01:00
2012-01-07 19:05:25 +00:00
class CaveForm ( ModelForm ) :
2023-01-30 19:04:36 +00:00
""" Only those fields for which we want to override defaults are listed here
2023-09-11 18:38:14 +01:00
the other fields of the class Cave are present on the form , but use the default presentation style
2023-01-30 19:04:36 +00:00
"""
2023-11-14 13:55:11 +00:00
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 " } ) )
2023-01-30 19:04:36 +00:00
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}))
2023-11-14 13:55:11 +00:00
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 " } )
)
2023-01-30 19:04:36 +00:00
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) " } ) ,
)
2023-11-14 13:55:11 +00:00
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 = " " )
2023-01-30 19:04:36 +00:00
survex_file = forms . CharField (
2023-04-30 19:00:22 +01:00
required = False , label = " Survex file eg. caves-1623/000/000.svx " , widget = forms . TextInput ( attrs = { " size " : " 45 " } )
2023-01-30 19:04:36 +00:00
)
2023-11-14 13:55:11 +00:00
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 " } ) )
2023-07-05 17:43:57 +01:00
#cave_slug = forms.CharField()
2023-01-30 19:04:36 +00:00
2012-01-07 19:05:25 +00:00
class Meta :
model = Cave
2023-11-03 14:54:57 +00:00
exclude = ( " filename " , " url " )
2023-04-30 19:00:22 +01:00
2023-11-14 13:55:11 +00:00
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 ' ]
2023-09-11 18:38:14 +01:00
2023-04-30 19:00:22 +01:00
def clean_cave_slug ( self ) :
if self . cleaned_data [ " cave_slug " ] == " " :
2023-09-11 18:38:14 +01:00
myArea = self . cleaned_data [ " areacode " ]
2023-04-30 19:00:22 +01:00
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- " , " - " )
2012-08-14 21:51:15 +01:00
def clean ( self ) :
2023-08-03 14:11:46 +01:00
cleaned_data = super ( CaveForm , self ) . clean ( ) # where is this code hidden? How does this work??
2023-04-30 19:00:22 +01:00
if self . data . get ( " kataster_number " ) == " " and self . data . get ( " unofficial_number " ) == " " :
2023-01-30 19:04:36 +00:00
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."])
2023-09-11 18:38:14 +01:00
if cleaned_data . get ( " url " ) == [ ] :
self . _errors [ " url " ] = self . error_class ( [ " This field is required. " ] )
2023-04-30 19:00:22 +01:00
if cleaned_data . get ( " url " ) and cleaned_data . get ( " url " ) . startswith ( " / " ) :
2021-04-14 16:28:30 +01:00
self . _errors [ " url " ] = self . error_class ( [ " This field cannot start with a /. " ] )
2023-04-30 19:00:22 +01:00
return cleaned_data
2012-08-14 21:51:15 +01:00
2023-01-30 19:04:36 +00:00
2012-06-10 14:59:21 +01:00
class EntranceForm ( ModelForm ) :
2023-01-30 19:04:36 +00:00
""" Only those fields for which we want to override defaults are listed here
2023-07-26 15:38:19 +01:00
the other fields are present on the form , but use the default presentation style
2023-01-30 19:04:36 +00:00
"""
2023-11-14 13:55:11 +00:00
name = forms . CharField ( required = False , widget = forms . TextInput ( attrs = { " size " : " 45 " , " placeholder " : " usually leave this blank " } ) )
2023-01-30 19:04:36 +00:00
entrance_description = forms . CharField (
required = False ,
2023-07-26 15:38:19 +01:00
widget = HTMLarea ( attrs = { " height " : " 80 % " , " rows " : 20 , " placeholder " : " Enter text (using HTML) " } ) ,
2023-01-30 19:04:36 +00:00
)
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 (
2023-11-14 13:55:11 +00:00
label = " Map (is this used?) " ,
2023-01-30 19:04:36 +00:00
required = False ,
2023-07-26 15:38:19 +01:00
widget = HTMLarea ( attrs = { " height " : " 80 % " , " rows " : 20 , " placeholder " : " Enter text (using HTML) " } ) ,
2023-01-30 19:04:36 +00:00
)
location_description = forms . CharField (
2023-11-14 13:55:11 +00:00
label = " Location " ,
2023-01-30 19:04:36 +00:00
required = False ,
2023-07-26 15:38:19 +01:00
widget = HTMLarea ( attrs = { " height " : " 80 % " , " rows " : 20 , " placeholder " : " Enter text (using HTML) " } ) ,
2023-01-30 19:04:36 +00:00
)
lastvisit = forms . CharField (
2023-11-14 13:55:11 +00:00
required = False , widget = forms . TextInput ( attrs = { " size " : " 10 " } ) , label = " Last visit date, e.g. 2023-07-11 "
2023-01-30 19:04:36 +00:00
)
approach = forms . CharField (
required = False ,
2023-07-26 15:38:19 +01:00
widget = HTMLarea ( attrs = { " height " : " 80 % " , " rows " : 20 , " placeholder " : " Enter text (using HTML) " } ) ,
2023-01-30 19:04:36 +00:00
)
underground_description = forms . CharField (
required = False ,
2023-07-26 15:38:19 +01:00
widget = HTMLarea ( attrs = { " height " : " 80 % " , " rows " : 20 , " placeholder " : " Enter text (using HTML) " } ) ,
2023-01-30 19:04:36 +00:00
)
photo = forms . CharField (
2023-11-14 13:55:11 +00:00
label = " Photos (use ' image ' button) " ,
2023-01-30 19:04:36 +00:00
required = False ,
2023-11-14 13:55:11 +00:00
widget = HTMLarea ( attrs = { " height " : " 80 % " , " rows " : 20 , " placeholder " : " Use button on right to add HTML link " } ) ,
2023-01-30 19:04:36 +00:00
)
marking_comment = forms . CharField (
2023-11-14 13:55:11 +00:00
label = " Marking text " ,
2023-01-30 19:04:36 +00:00
required = False ,
2023-11-14 13:55:11 +00:00
widget = HTMLarea ( attrs = { " height " : " 80 % " , " rows " : 20 , " placeholder " : " Enter exact tag text, e.g. ' CUCC 2035 ZB-03 ' " } ) ,
2023-01-30 19:04:36 +00:00
)
findability_description = forms . CharField (
required = False ,
2023-11-14 13:55:11 +00:00
label = " How to find it " ,
2023-07-26 15:38:19 +01:00
widget = HTMLarea ( attrs = { " height " : " 80 % " , " rows " : 20 , " placeholder " : " Enter text (using HTML) " } ) ,
2023-01-30 19:04:36 +00:00
)
other_description = forms . CharField (
2023-11-14 13:55:11 +00:00
label = " Other comments " ,
2023-01-30 19:04:36 +00:00
required = False ,
2023-11-14 13:55:11 +00:00
widget = HTMLarea ( attrs = { " height " : " 80 % " , " rows " : 20 , " placeholder " : " Usually blank " } ) ,
2023-01-30 19:04:36 +00:00
)
bearings = forms . CharField (
2023-11-14 13:55:11 +00:00
label = " Bearings (obsolete) " ,
2023-01-30 19:04:36 +00:00
required = False ,
2023-11-14 13:55:11 +00:00
widget = HTMLarea ( attrs = { " height " : " 80 % " , " rows " : 20 , " placeholder " : " Usually blank " } ) ,
2023-07-26 15:38:19 +01:00
)
tag_station = forms . CharField (
required = False ,
2023-11-14 13:55:11 +00:00
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 "
2023-07-26 15:38:19 +01:00
)
other_station = forms . CharField (
required = False ,
2023-11-14 13:55:11 +00:00
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 "
2023-01-30 19:04:36 +00:00
)
2023-10-11 22:25:24 +01:00
2023-07-26 15:38:19 +01:00
lat_wgs84 = forms . CharField (
2023-11-14 13:55:11 +00:00
required = False , widget = forms . TextInput ( attrs = { " size " : " 10 " , " placeholder " : " e.g. 47.123456 " } ) ,
label = " Latitude (WSG84) - if no other location "
2023-07-26 15:38:19 +01:00
)
2023-01-30 19:04:36 +00:00
long_wgs84 = forms . CharField (
2023-11-14 13:55:11 +00:00
required = False , widget = forms . TextInput ( attrs = { " size " : " 10 " , " placeholder " : " e.g. 13.123456 " } ) ,
label = " Longitude (WSG84) - if no other location "
2023-07-26 15:38:19 +01:00
)
2023-10-11 22:58:20 +01:00
alt = forms . CharField ( required = False , label = " Altitude (m) - from GPS if you have it, but let it settle. " )
2023-11-14 13:55:11 +00:00
# url = forms.CharField(required=False, label="URL [usually blank]", widget=forms.TextInput(attrs={"size": "45"}))
2023-01-30 19:04:36 +00:00
2023-11-14 13:55:11 +00:00
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 ' ]
2023-04-30 21:41:17 +01:00
2012-06-10 14:59:21 +01:00
class Meta :
model = Entrance
2023-01-30 19:04:36 +00:00
exclude = (
" cached_primary_slug " ,
2023-11-14 13:55:11 +00:00
" filename " ,
" slug "
2023-01-30 19:04:36 +00:00
)
2015-09-16 01:52:45 +01:00
def clean ( self ) :
if self . cleaned_data . get ( " url " ) . startswith ( " / " ) :
2021-04-14 16:28:30 +01:00
self . _errors [ " url " ] = self . error_class ( [ " This field cannot start with a /. " ] )
2015-09-16 01:52:45 +01:00
return self . cleaned_data
2012-06-10 14:59:21 +01:00
2012-01-07 19:05:25 +00:00
2023-03-28 20:30:00 +01:00
# This next line is called from the templates/edit_cave.html template.
2022-03-17 00:41:29 +00:00
# This is sufficient to create an entire entry for for the cave fields automatically
2020-08-02 23:53:35 +01:00
# http://localhost:8000/cave/new/
2023-02-10 00:05:04 +00:00
# using django built-in Deep Magic. https://docs.djangoproject.com/en/dev/topics/forms/modelforms/
2022-03-17 00:41:29 +00:00
# for forms which map directly onto a Django Model
2023-01-30 19:04:36 +00:00
CaveAndEntranceFormSet = modelformset_factory ( CaveAndEntrance , exclude = ( " cave " , ) )
2023-03-28 20:30:00 +01:00
# This is used only in edit_entrance() in views/caves.py
2012-01-07 19:05:25 +00:00
2012-08-14 21:51:15 +01:00
class EntranceLetterForm ( ModelForm ) :
2023-01-30 19:04:36 +00:00
""" 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 .
2022-08-01 15:04:22 +01:00
With entrances gaining new caves and letters when caves are joined .
2023-01-30 19:04:36 +00:00
"""
2023-11-05 13:20:45 +00:00
# This only needs to be required=True for the second and subsequent entrances, not the first. Tricky.
2023-11-07 00:12:57 +00:00
entranceletter = forms . CharField ( required = False , widget = forms . TextInput ( attrs = { " size " : " 2 " } ) )
2023-01-30 19:04:36 +00:00
2012-08-14 21:51:15 +01:00
class Meta :
model = CaveAndEntrance
2023-01-30 19:04:36 +00:00
exclude = ( " cave " , " entrance " )
2022-08-01 15:04:22 +01:00
def full_clean ( self ) :
super ( EntranceLetterForm , self ) . full_clean ( )
try :
self . instance . validate_unique ( )
except forms . ValidationError as e :
self . _update_errors ( e )