forms.py 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. from django import forms
  2. from .models import Contrib
  3. import re
  4. ORIENTATIONS = (
  5. ('N', 'Nord'),
  6. ('NO', 'Nord-Ouest'),
  7. ('O', 'Ouest'),
  8. ('SO', 'Sud-Ouest'),
  9. ('S', 'Sud'),
  10. ('SE', 'Sud-Est'),
  11. ('E', 'Est'),
  12. ('NE', 'Nord-Est'),
  13. )
  14. class PublicContribForm(forms.ModelForm):
  15. human_field = forms.CharField(required=False, widget=forms.HiddenInput)
  16. class Meta:
  17. model = Contrib
  18. fields = [
  19. 'name', 'contrib_type',
  20. 'latitude', 'longitude',
  21. 'phone', 'email',
  22. 'comment',
  23. 'access_type',
  24. 'floor', 'floor_total', 'orientations', 'roof',
  25. 'comment',
  26. 'privacy_name', 'privacy_email', 'privacy_coordinates',
  27. 'privacy_place_details', 'privacy_comment',
  28. ]
  29. widgets = {
  30. 'contrib_type': forms.RadioSelect,
  31. 'latitude': forms.HiddenInput,
  32. 'longitude': forms.HiddenInput,
  33. 'access_type': forms.RadioSelect,
  34. 'comment': forms.Textarea({'rows': 3}),
  35. 'floor': forms.TextInput(
  36. attrs={'placeholder': "Étage (0 pour RDC)"}),
  37. 'floor_total': forms.TextInput(
  38. attrs={'placeholder': "Nb. d'étages du bâtiment"}),
  39. }
  40. # Widget rendering is managed by hand in template for orientions.
  41. orientations = forms.MultipleChoiceField(choices=ORIENTATIONS)
  42. _privacy_fieldnames = (
  43. 'privacy_name', 'privacy_email', 'privacy_coordinates',
  44. 'privacy_place_details', 'privacy_comment',
  45. )
  46. def _validate_contact_information(self, data):
  47. if (data.get('phone') == '') and (data.get('email') == ''):
  48. msg = 'Il faut remplir un des deux champs "téléphone" ou "email".'
  49. self.add_error('phone', msg)
  50. self.add_error('email', msg)
  51. def _validate_floors(self, data):
  52. if None in (data.get('floor'), data.get('floor_total')):
  53. return
  54. if (data.get('floor') > data.get('floor_total')):
  55. self.add_error(
  56. 'floor',
  57. "L'étage doit être inférieur ou égal au nombre d'étages",
  58. )
  59. def _validate_share_fields(self, data):
  60. if data.get('contrib_type') == Contrib.CONTRIB_SHARE:
  61. if data.get('access_type') == '':
  62. self.add_error('access_type', 'Ce champ est requis')
  63. #tetaneutral.net: comment with link to photos required for new connection request
  64. def _validate_comment(self, data):
  65. if data.get('contrib_type') == Contrib.CONTRIB_CONNECT and re.search('https?://', data.get('comment')) is None:
  66. self.add_error('comment', 'Des photos de la vue depuis votre toit ou balcon sont nécessaires pour déterminer votre éligibilité à une connexion radio. Vous pouvez les déposer chez un hébergeur (par exemple https://framapic.org ) et mettre le lien d\'accès à ces photos ici.')
  67. def clean(self):
  68. cleaned_data = super().clean()
  69. self._validate_contact_information(cleaned_data)
  70. self._validate_floors(cleaned_data)
  71. self._validate_share_fields(cleaned_data)
  72. #tetaneutral.net: comment with link to photos required for new connection request
  73. self._validate_comment(cleaned_data)
  74. return cleaned_data
  75. def privacy_fields(self):
  76. for i in self._privacy_fieldnames:
  77. field = self[i]
  78. # FIXME: What a hack
  79. field.label = field.label\
  80. .replace('public', '')\
  81. .replace('publiques', '')
  82. yield field
  83. def __init__(self, *args, **kwargs):
  84. super(PublicContribForm, self).__init__(*args, **kwargs)
  85. for f in ['latitude', 'longitude']:
  86. self.fields[f].error_messages['required'] = "Veuillez déplacer le curseur à l'endroit où vous voulez partager/accéder au service"
  87. class ManageActionForm(forms.Form):
  88. ACTION_DELETE = 'delete'
  89. ACTION_RENEW = 'renew'
  90. action = forms.ChoiceField(
  91. widget=forms.HiddenInput(),
  92. choices=(
  93. (ACTION_DELETE, ACTION_DELETE),
  94. (ACTION_RENEW, ACTION_RENEW),
  95. ))