ojuso-map/apps/map/forms.py

522 lines
18 KiB
Python
Raw Normal View History

2017-11-18 16:54:44 +00:00
from django import forms
from django.urls import reverse, reverse_lazy
2018-04-02 09:59:37 +00:00
from django.utils.safestring import mark_safe
from django.utils.text import format_lazy
from django.utils.translation import ugettext_lazy as _
2017-06-16 16:06:22 +00:00
from crispy_forms.helper import FormHelper
from crispy_forms.layout import Submit, Layout, HTML, Fieldset, Div
2017-11-18 16:54:44 +00:00
from crispy_forms.bootstrap import Tab, TabHolder, PrependedText, FormActions
from dal import autocomplete
2017-06-16 16:06:22 +00:00
from leaflet.forms.widgets import LeafletWidget
from apps.files.models import File, ImageFile
2018-04-23 05:15:33 +00:00
from .models import CaseStudy, SpatialRefSys, PointOfInterest
from .widgets import JSONFileListWidget
2017-06-16 16:06:22 +00:00
2018-12-02 01:10:12 +00:00
SECTOR_HELP = {
2019-03-18 16:41:58 +00:00
'RN': _("Including electricity, heat or combined heat and power generation"),
2018-12-02 01:10:12 +00:00
'PG': '',
'ST': _('Biological, chemical, electrical, electromagnetic, electrochemical,'
' mechanical including gravitational potential, thermal, etc.'),
2019-03-18 16:41:58 +00:00
'SM': _("Including supply of minerals"),
2018-12-02 01:10:12 +00:00
'MA': '',
}
POWER_TECHNOLOGY_HELP = {
'PT': _('Lines, transformers, machinery, etc.'),
2018-12-02 01:10:12 +00:00
'HN': _('District heating/cooling, etc.'),
'OT': '',
}
def add_explanatory_text(model_choices, explanatory_text):
return [
(
choice[0],
mark_safe('<b>%s</b><br><span class="text-muted">%s</span>' %
(choice[1], explanatory_text[choice[0]])
)
) for choice in model_choices
]
class MinimumZoomWidget(LeafletWidget):
geometry_field_class = 'MinimumZoomField'
class PointOfInterest(forms.models.ModelForm):
def __init__(self, *args, **kwargs):
super(PointOfInterest, self).__init__(*args, **kwargs)
self.helper = FormHelper(self)
self.helper.form_id = 'case-study-form'
self.helper.form_class = 'form-horizontal'
self.helper.form_method = 'post'
self.helper.form_action = 'add'
self.helper.label_class = 'col-lg-2'
self.helper.field_class = 'col-lg-10'
self.helper.include_media = False
self.helper.form_action = reverse('point-of-interest-form')
self.helper.add_input(
Submit('submit', _('Submit'), css_class='btn-success center-block')
)
class Meta:
model = PointOfInterest
widgets = {
'location': MinimumZoomWidget(attrs={
'settings_overrides': {
'SCALE': False
}
}),
}
fields = [
'title',
'location',
'synopsis',
'link',
]
class BaseCaseStudyForm(forms.models.ModelForm):
2017-10-09 23:58:36 +00:00
"""Base form class for the CaseStudy model."""
2017-06-16 16:06:22 +00:00
def __init__(self, *args, **kwargs):
super(BaseCaseStudyForm, self).__init__(*args, **kwargs)
self.helper = FormHelper(self)
2017-06-16 16:06:22 +00:00
self.helper.form_id = 'case-study-form'
self.helper.form_class = 'form-horizontal'
self.helper.form_method = 'post'
2018-11-26 21:14:18 +00:00
self.helper.label_class = 'col-md-3'
self.helper.field_class = 'col-md-9'
self.helper.include_media = False
2017-06-16 16:06:22 +00:00
2019-04-27 22:36:58 +00:00
# Parse number fields correctly for the locale
number_fields = [
"area_of_land",
"total_generation_capacity",
"total_investment",
"energy_storage_capacity",
"energy_transmission_capacity",
"area_of_land",
"total_generation_capacity",
"total_investment",
]
for field_name in number_fields:
if field_name in self.fields:
self.fields[field_name].localize = True
2017-06-16 16:06:22 +00:00
class Meta:
model = CaseStudy
fields = '__all__'
2017-11-18 16:54:44 +00:00
widgets = {
'location': MinimumZoomWidget(attrs={
'settings_overrides': {
'SCALE': False
}
}),
2017-11-18 16:54:44 +00:00
}
class ShortCaseStudyForm(BaseCaseStudyForm):
2017-10-09 23:58:36 +00:00
"""Short version of the CaseStudy form."""
def __init__(self, *args, **kwargs):
super(ShortCaseStudyForm, self).__init__(*args, **kwargs)
self.helper.add_input(Submit('submit', _('Submit'), css_class='btn-success center-block'))
2017-10-09 23:58:36 +00:00
2019-04-27 22:19:34 +00:00
self.fields['sector_of_economy'].widget = forms.RadioSelect()
self.fields['sector_of_economy'].required = False
self.fields['sector_of_economy'].choices = add_explanatory_text(
CaseStudy.SECTOR_CHOICES,
SECTOR_HELP
2018-12-02 01:10:12 +00:00
)
class Meta(BaseCaseStudyForm.Meta):
fields = [
'entry_name',
'location',
'sector_of_economy',
'positive_or_negative',
'country',
'area_of_land',
'land_ownership',
'land_ownership_details',
'location_context',
'type_of_ecosystem',
'describe_ecosystem',
2018-11-24 16:54:39 +00:00
'affected_communities',
'project_status',
'synopsis',
'full_description',
'video',
'media_coverage_mainstream',
'media_coverage_independent',
'community_voices'
]
class BootstrapClearableFileInput(forms.ClearableFileInput):
template_name = 'map/forms/widgets/file.html'
def PreviousButton():
return HTML(
format_lazy(
"<a class='btn btn-primary btnPrevious'>{prev}</a>",
prev=_("Previous")
)
)
def NextButton():
return HTML(
format_lazy(
"<a class='btn btn-primary btnNext pull-right'>{next}</a>",
next=_("Next")
)
)
class LongCaseStudyForm(BaseCaseStudyForm):
2017-10-09 23:58:36 +00:00
"""Long version of the CaseStudy form."""
2018-04-02 09:59:37 +00:00
images = forms.FileField(
2019-04-27 22:19:34 +00:00
label=_("Images"),
widget=BootstrapClearableFileInput(attrs={
'url': reverse_lazy('files:upload'),
'field': 'images_files',
2019-04-27 22:19:34 +00:00
}),
required=False
)
images_files = forms.ModelMultipleChoiceField(
queryset=ImageFile.objects.all(),
widget=JSONFileListWidget(),
required=False
)
2018-04-23 05:15:33 +00:00
official_project_documents = forms.FileField(
2019-04-27 22:19:34 +00:00
label=_("Official project documents"),
widget=BootstrapClearableFileInput(attrs={
'url': reverse_lazy('files:upload'),
'field': 'official_project_documents_files',
2018-04-23 05:15:33 +00:00
}), required=False
)
official_project_documents_files = forms.ModelMultipleChoiceField(
queryset=File.objects.all(),
widget=JSONFileListWidget(),
2018-04-23 05:15:33 +00:00
required=False
)
other_documents = forms.FileField(
2019-04-27 22:19:34 +00:00
label=_("Other documents"),
widget=BootstrapClearableFileInput(attrs={
'url': reverse_lazy('files:upload'),
'field': 'other_documents_files',
2018-04-23 05:15:33 +00:00
}), required=False
)
other_documents_files = forms.ModelMultipleChoiceField(
queryset=File.objects.all(),
widget=JSONFileListWidget(),
2018-04-23 05:15:33 +00:00
required=False
)
shapefiles = forms.FileField(
label=CaseStudy.shapefiles_label,
help_text=CaseStudy.shapefiles_help_text,
widget=BootstrapClearableFileInput(attrs={
'url': reverse_lazy('files:upload'),
'field': 'shapefiles_files',
2018-04-23 05:15:33 +00:00
}), required=False
)
shapefiles_files = forms.ModelMultipleChoiceField(
queryset=File.objects.all(),
widget=JSONFileListWidget(),
2018-04-23 05:15:33 +00:00
required=False
)
coordinate_reference_system = forms.ModelChoiceField(
2019-04-27 22:19:34 +00:00
label=_("Coordinate reference system"),
queryset=SpatialRefSys.objects.all(),
widget=autocomplete.ModelSelect2(url='srs-autocomplete'),
initial=4326,
)
2018-11-24 16:54:39 +00:00
def __init__(self, *args, **kwargs):
super(LongCaseStudyForm, self).__init__(*args, **kwargs)
2018-11-26 22:34:06 +00:00
self.fields['positive_case_type'].label = ""
self.fields['negative_case_reasons'].label = ""
2018-11-24 16:54:39 +00:00
2019-04-27 22:19:34 +00:00
self.fields['sector_of_economy'].widget = forms.RadioSelect()
self.fields['sector_of_economy'].required = False
self.fields['sector_of_economy'].choices = add_explanatory_text(
CaseStudy.SECTOR_CHOICES,
SECTOR_HELP
2018-04-02 09:59:37 +00:00
)
2019-04-27 22:19:34 +00:00
self.fields['power_technology'].widget = forms.RadioSelect()
self.fields['power_technology'].required = False
self.fields['power_technology'].choices = add_explanatory_text(
CaseStudy.POWER_TECHNOLOGY_CHOICES,
POWER_TECHNOLOGY_HELP
2018-11-24 17:58:08 +00:00
)
self.fields['project_owners'].required = True
self.fields['shareholders'].required = True
organising_vs_label = _(
'Socio-environmental impacts (negative and potentially positive)')
organising_pro_label = _(
'Socio-environmental impacts (positive and potentially negative)')
organising_other_label = _(
'Socio-environmental impacts (positive and negative)')
self.fields['socioeconomic_benefits'].label = format_lazy(
(
'<span class="organising organising-vs">{vs}</span>'
'<span class="organising organising-pro">{pro}</span>'
'<span class="organising organising-none organising-idk">{other}</span>'
),
vs=organising_vs_label,
pro=organising_pro_label,
other=organising_other_label
)
organising_other_text = _(
'Please expand on your response given in the full description on page one.'
' For example, for positive impacts you need to go beyond emissions'
' savings, paying rent for land, or complying with environmental or social'
' legislation. For negative impacts you need to focus on substantive'
' impacts on vulnerable groups, violations of land rights or abusive labour'
' practices.')
organising_vs_text = _(
'Please expand on your response given in the description. Note that we aim'
' to focus on violation of land rights / human rights / collective rights,'
' substantive negative impacts on vulnerable groups, aggression / threats /'
2019-04-21 12:28:03 +00:00
' violence, severe environmental and/or cultural impacts, abusive labor'
' practices, and corruption / governance issues, but feel free to cover any'
' additional aspect that you consider relevant. Please also describe and'
' analyze socio-environmental impacts that could be presented or considered'
' as positive.')
organising_pro_text = _(
'Please expand on your response given in the description. Please also'
' describe and analyze socio-environmental impacts that could be considered'
' as negative.')
self.fields['socioeconomic_benefits'].help_text = format_lazy(
(
'<span class="organising organising-none organising-idk">{other}</span>'
'<span class="organising organising-vs">{vs}</span>'
'<span class="organising organising-pro">{pro}</span>'
),
vs=organising_vs_text,
pro=organising_pro_text,
other=organising_other_text
)
2018-11-25 13:48:52 +00:00
2017-10-09 23:58:36 +00:00
self.helper.form_action = reverse('long-form')
self.helper.layout = Layout(
TabHolder(
2017-11-18 16:54:44 +00:00
Tab(_("Basic information"),
'entry_name',
'location',
'country',
2018-11-25 13:48:52 +00:00
'shapefiles',
'shapefiles_files',
'coordinate_reference_system',
'name_of_territory_or_area',
'area_of_land',
'land_ownership',
'land_ownership_details',
'location_context',
'type_of_ecosystem',
'describe_ecosystem',
2018-11-25 13:48:52 +00:00
'affected_communities',
2018-11-26 22:34:06 +00:00
'people_affected_other',
'project_status',
2018-11-26 23:56:36 +00:00
'start_year',
'completion_year',
'synopsis',
'full_description',
'images',
'images_files',
'video',
2017-11-18 16:54:44 +00:00
'video_caption',
'video_credit',
Fieldset(
2019-03-18 16:41:58 +00:00
_("Owners and financiers"),
'project_owners',
2018-11-24 16:54:39 +00:00
'consultants_contractors',
'shareholders',
'financial_institutions',
'financial_institutions_other',
),
Fieldset(
_("Media reports and other communications"),
'media_coverage_mainstream',
'media_coverage_independent',
'community_voices',
'direct_comms',
'social_media_links'
),
2017-11-18 16:54:44 +00:00
FormActions(
NextButton()
2017-11-18 16:54:44 +00:00
)
),
Tab(
2017-11-18 16:54:44 +00:00
_("Technical and economic analysis"),
'sector_of_economy',
2018-11-26 22:34:06 +00:00
Div(
2018-11-24 17:58:08 +00:00
'generation_type',
2017-11-18 16:54:44 +00:00
'generation_technology',
2018-11-26 22:34:06 +00:00
css_class='power_generation_questions'
),
Div(
'power_technology',
css_class='energy_network_questions'
),
Div(
'energy_details',
css_class='energy_generation_network_and_storage_questions'
),
Div(
2017-11-18 16:54:44 +00:00
'biomass_detail',
'total_generation_capacity',
2018-11-26 22:34:06 +00:00
css_class='power_generation_questions'
2017-11-18 16:54:44 +00:00
),
2018-11-26 22:34:06 +00:00
Div(
2018-11-24 18:30:58 +00:00
'energy_transmission_capacity',
2018-11-26 22:34:06 +00:00
css_class='energy_network_questions'
),
Div(
'energy_storage_capacity',
css_class='energy_storage_questions'
),
Div(
PrependedText('total_investment', 'USD $'),
2017-11-18 16:54:44 +00:00
'contractor_or_supplier_of_technology',
2018-11-26 22:34:06 +00:00
'energy_customers',
2017-11-18 16:54:44 +00:00
'additional_technical_details',
2018-11-26 22:34:06 +00:00
css_class='energy_generation_network_and_storage_questions'
2017-11-18 16:54:44 +00:00
),
2018-11-26 22:34:06 +00:00
Div(
2017-11-18 16:54:44 +00:00
'minerals_or_commodities',
'minerals_or_commodities_other',
'use_in_energy_economy',
'use_in_energy_economy_other',
'project_life_span',
'size_of_concessions',
'projected_production_of_commodities',
'type_of_extraction',
'associated_infrastructure',
2018-11-26 22:34:06 +00:00
css_class="mineral_commodity_questions"
2017-11-18 16:54:44 +00:00
),
2018-11-26 22:34:06 +00:00
Div(
2018-11-24 21:09:35 +00:00
'manufacturing_type',
'manufacturing_description',
'manufacturing_related_tech',
'manufacturing_factors',
'manufacturing_factors_description',
'manufacturing_ownership',
2018-11-26 22:34:06 +00:00
css_class="manufacturing_questions"
2018-11-24 21:09:35 +00:00
),
2017-11-18 16:54:44 +00:00
FormActions(
PreviousButton(),
NextButton()
2017-11-18 16:54:44 +00:00
)
),
Tab(
_("Socio-environmental analysis"),
HTML(
format_lazy(
"<p>{text}</p>",
text=_(
2019-04-21 12:28:03 +00:00
"In the following, we expect the analysis to reflect"
" the perspective of the organization(s) or person(s)"
" describing the case.")
)
),
'positive_or_negative',
2018-11-26 22:34:06 +00:00
Div(
HTML(
format_lazy(
"<label class='col-md-3 control-label'>{text}</label>",
text=_("What kind of case is this entry about?")
)
),
2018-11-26 22:34:06 +00:00
Div(
'positive_case_type',
'negative_case_reasons',
css_class='col-md-9',
),
css_class='form-group',
),
2018-11-25 13:48:52 +00:00
'negative_case_reasons_other',
'socioeconomic_benefits',
'isolated_or_widespread',
'key_actors_involved',
'project_status_detail',
'obstacles_and_hindrances',
'negative_socioenvironmental_impacts',
'when_did_organising_start',
'who_has_been_involved',
'participation_mechanisms',
'identified_partnerships',
2018-03-31 05:29:25 +00:00
Div(
2018-11-26 22:34:06 +00:00
css_class="common_questions"
2017-11-18 16:54:44 +00:00
),
FormActions(
PreviousButton(),
NextButton()
2017-11-18 16:54:44 +00:00
)
),
2018-03-31 05:29:25 +00:00
Tab(
_("Contact details"),
'contact_email',
'contact_phone',
'contact_website',
PrependedText('contact_twitter', '@', placeholder='username'),
'contact_facebook',
'contact_other',
'shown_on_other_platforms',
'shown_on_other_platforms_detail',
2018-03-31 05:29:25 +00:00
FormActions(
PreviousButton(),
NextButton()
2018-03-31 05:29:25 +00:00
)
),
2017-11-18 16:54:44 +00:00
Tab(
_("Uploads"),
'official_project_documents',
2018-04-23 05:15:33 +00:00
'official_project_documents_files',
2017-11-18 16:54:44 +00:00
'other_documents',
2018-04-23 05:15:33 +00:00
'other_documents_files',
2017-11-18 16:54:44 +00:00
FormActions(
PreviousButton(),
2017-11-18 16:54:44 +00:00
Submit('submit', _('Submit'), css_class="btn-success pull-right")
)
)))
class Meta(BaseCaseStudyForm.Meta):
exclude = ('approved',)
2018-04-23 05:15:33 +00:00
class Media:
js = (
'files/upload.js',
)