ojuso-map/apps/map/models.py
2018-05-24 20:52:43 -04:00

1100 lines
36 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import datetime
from urllib import parse
from django.contrib.auth.models import User
from django.contrib.gis.db import models
from django.db import connection
from django.template.defaultfilters import slugify
from django.utils.translation import ugettext as _
from django_extensions.db.fields import AutoSlugField
from django_countries.fields import CountryField
from multiselectfield import MultiSelectField
from phonenumber_field.modelfields import PhoneNumberField
from . import validators
class CaseStudyDraft(models.Model):
author = models.ForeignKey(
User, on_delete=models.CASCADE
)
data = models.TextField()
class SpatialRefSys(connection.ops.spatial_ref_sys()):
def __str__(self):
return self.__unicode__()
def __unicode__(self):
return '{0.auth_name}:{0.auth_srid} {0.name}'.format(self)
class Meta:
proxy = True
verbose_name = "spatial reference system"
class CaseStudyQuerySet(models.QuerySet):
def approved(self):
return self.filter(
approved=True
)
class CaseStudy(models.Model):
"""Model for case studies submitted to the Ojuso Platform"""
approved = models.BooleanField(default=False)
# Choice lists for drop-downs
SECTOR_CHOICES = (
('RN', _('Renewable Energy Generation')),
('PG', _('Power Grids')),
('SM', _('Supply of Minerals')),
)
POSITIVE_NEGATIVE_CHOICES = (
('P', _('Positive')),
('N', _('Negative'))
)
LAND_OWNERSHIP_CHOICES = (
('PRI', _('Private Land')),
('PUB', _('Public Land')),
('COM', _('Community Land')),
('OTH', _('Other')),
)
LOCATION_CONTEXT_CHOICES = (
('RUR', _('Rural')),
('URB', _('Urban')),
('MIX', _('Mixed')),
)
TYPE_OF_ECOSYSTEM_CHOICES = (
('MARINE', _('Marine (e.g. Ocean, Sea)')),
('FRESH', _('Freshwater (e.g. Freshwater, Lake)')),
('FOREST', _('Forest/Jungle')),
('AGRI', _('Agricultural Land')),
('GRASS', _('Grassland')),
('DESERT', _('Desert (Tundra, Ice or Sand)')),
('WETLND', _('Wetland (Marsh, Mangrove, Peat Soil)')),
('URBAN', _('Urban'))
)
PROJECT_STATUS_CHOICES = (
('EXSTNG', _('Existing Project')),
('UCONST', _('Under Construction')),
('PROJCD', _('Projected Project')),
)
FINANCIAL_INSTITUTIONS = (
('AfDB', _('African Development Bank (AfDB)')),
('BADEA', _('Arab Bank for Economic Development in Africa (BADEA)')),
('ADB', _('Asian Development Bank (ADB)')),
('AIIB', _('Asian Infrastructure Investment Bank (AIIB)')),
('BSTDB', _('Black Sea Trade and Development Bank (BSTDB)')),
('CAF', _('Corporacion Andina de Fomento / Development Bank of Latin America (CAF)')),
('CDB', _('Caribbean Development Bank (CDB)')),
('CABEI', _('Central American Bank for Economic Integration (CABEI)')),
('EADB', _('East African Development Bank (EADB)')),
('ETDB', _('Economic Cooperation Organization Trade and Development Bank (ETDB)')),
('EDB', _('Eurasian Development Bank (EDB)')),
('EBRD', _('European Bank for Reconstruction and Development (EBRD)')),
('EC', _('European Commission (EC)')),
('EIB', _('European Investment Bank (EIB)')),
('IADB', _('Inter-American Development Bank Group (IDB, IADB)')),
('IFFIm', _('International Finance Facility for Immunisation (IFFIm)')),
('IFAD', _('International Fund for Agricultural Development (IFAD)')),
('IIB', _('International Investment Bank (IIB)')),
('IsDB', _('Islamic Development Bank (IsDB)')),
('FMO', _('Nederlandse Financieringsmaatschappij voor Ontwikkelingslanden NV (FMO)')),
('NDB', _('New Development Bank (NDB) (formerly BRICS Development Bank)')),
('NDF', _('The Nordic Development Fund')),
('NIB', _('Nordic Investment Bank (NIB)')),
('OFID', _('OPEC Fund for International Development (OFID)')),
('BOAD', _('West African Development Bank (BOAD)')),
('WB', _('World Bank')),
)
GENERATION_TECHNOLOGY_CHOICES = (
(_('Wind energy'), (
('SSWE', _('Small-scale (less than 500kW)')),
('LSWE', _('Large-scale (more than 500kW)'))
)),
(_('Photovoltaic electricity'), (
('SSPV', _('Small-scale (less than 500kW)')),
('LSPV', _('Large-scale (more than 500kW)'))
)),
(_('Hydroelectric'), (
('SHYD', _('Small-scale (less than 1MW)')),
('MHYD', _('Medium-scale (between 1-20MW)')),
('LHYD', _('Large-scale (more than 20MW - often not considered renewable)')),
)),
('STHE', _('Solar thermal electricity (e.g using parabolic reflectors)')),
('GEOT', _('Geothermal electricity')),
('BIOG', _('Biogas turbine')),
('OTHB', _('Other biomass (including liquid/solid biofuel)')),
('OTHR', _('Other (tidal, wave etc)'))
)
POWER_TECHNOLOGY_CHOICES = (
('PT', _('Power transmission (grid lines, substations etc)')),
('ES', _('Energy storage (pumped storage, compressed air, battery systems etc')),
('OT', _('Others'))
)
TYPE_OF_EXTRACTION_CHOICES = (
('SUR', _('Surface (open pit/open cast/open cut mining)')),
('SUB', _('Sub-surface (underground mining)')),
('SEA', _('Seabed mining')),
('URB', _('Urban mining/recycling'))
)
MINERAL_COMMODITY_CHOICES = (
('ALU', _('Aluminium (Bauxite)')),
('ARS', _('Arsenic')),
('BER', _('Beryllium')),
('CAD', _('Cadmium')),
('CHR', _('Chromium')),
('COK', _('Coking')),
('COA', _('Coal (for steel)')),
('COP', _('Copper')),
('GAL', _('Gallium')),
('GER', _('Germanium')),
('GLD', _('Gold')),
('HRE', _('Heavy Rare Earth Elements (Gadolinium, Terbium, Dysprosium, Holmium, Erbium, Thulium, Ytterbium, Lutetium, Yttrium, Scandium)')),
('IRN', _('Iron')),
('LRE', _('Light Rare Earth Elements (Lanthanum, Cerium, Praseodymium, Neodymium, Promethium, Samarium, Europium)')),
('LED', _('Lead')),
('LIT', _('Lithium')),
('MAN', _('Manganese')),
('MER', _('Mercury')),
('MOL', _('Molybdenum')),
('NIC', _('Nickel')),
('NIO', _('Niobium')),
('PGM', _('Platinum group metals (ruthenium, rhodium, palladium, osmium, iridium, and platinum)')),
('RHE', _('Rhenium')),
('SIL', _('Silicon')),
('SIV', _('Silver')),
('TAN', _('Tantalum')),
('TEL', _('Tellurium')),
('THA', _('Thallium')),
('TIN', _('Tin')),
('TIT', _('Titanium')),
('TUN', _('Tungsten')),
('VAN', _('Vanadium')),
('ZNC', _('Zinc')),
('OTR', _('Other'))
)
USE_IN_ENERGY_ECONOMY_CHOICES = (
('WTM', _('Wind turbine manufacturing')),
('SPM', _('Solar panel manufacturing')),
('STM', _('Solar thermal system manufacturing')),
('HGM', _('Hydropower generator manufacturing')),
('GGM', _('Geothermal generator manufacturing')),
('ESS', _('Energy storage (inc. battery systems)')),
('OTR', _('Others'))
)
POSITIVE_CASE_TYPE_CHOICES = (
('CREP', _('Community renewable energy project')),
('EACP', _('Energy as a commons project')),
('PSEP', _('Public/state (federal, state, municipal) energy project')),
('CORS', _('A case of responsible sourcing/supply chain/lifecycle management')),
)
NEGATIVE_CASE_REASONS_OTHER_TEXT = _('Other reasons')
NEGATIVE_CASE_REASONS_CHOICES = (
('VOLR', _('Violation of land rights')),
('VOHR', _('Violation of fundamental human rights, indigenous rights and/or other collective rights')),
('EIMP', _('Environmental impacts (severe impacts on ecosystems / violation of laws, plans or programs of \
environmental conservation or territorial governance systems etc.')),
('NCUL', _('Negative cultural impacts (erosion/destruction of bio-cultural heritage, impacts on sacred land \
etc)')),
('AGGR', _('Aggression/threats to community members opposed to the project, collaboration with organized crime \
etc')),
('ALAB', _('Abusive labour practices')),
('CRUP', _('Corruption and/or irregular permitting or contracting, conflicts of interest etc')),
#
# N.B.
# If you add another field in here, you need to edit conditionalCheckboxes
# in templates/map/form.html and increment the check for the 'other' field there.
# If you don't, the 'other' detail entry won't show and hide at the appropriate
# times.
#
('OTHR', NEGATIVE_CASE_REASONS_OTHER_TEXT)
)
# Dynamically generate a list of choices 40 years prior and after the current year.
YEAR_CHOICES = [(r, r) for r in
range((datetime.datetime.now().year - 40),
(datetime.datetime.now().year + 41))]
##
# Meta Fields
##
# User who submitted case study
author = models.ForeignKey(
User,
models.SET_NULL,
blank=True,
null=True,
editable=False
)
# Date and time of submission
date_created = models.DateTimeField(auto_now_add=True, null=False)
# Slug derived from entry_name, used in urls for SEO
slug = AutoSlugField(populate_from=['entry_name'], editable=False)
##
# First Screen - Basic information
##
# 1.1
entry_name = models.CharField(
verbose_name=_("Entry Name"),
help_text=_("Enter the name of the entry. This should usually be the\
name of project."),
max_length=128
)
# N/A - Not explicitly listed in spec
location = models.PointField(
verbose_name=_("Project location")
)
# 1.2
sector_of_economy = models.CharField(
verbose_name=_("Sector of economy"),
help_text=_("Which sector of the renewable energy economy is most\
relevant?"),
max_length=3,
choices=SECTOR_CHOICES
)
# 1.3
positive_or_negative = models.CharField(
verbose_name=_("Positive or negative?"),
help_text=_("Is the case study a positive case or a negative case?"),
max_length=1,
choices=POSITIVE_NEGATIVE_CHOICES
)
# 1.4
country = CountryField(
verbose_name=_("Country"),
help_text=_("Select the country of the project")
)
# 1.5.1
area_of_land = models.IntegerField(
verbose_name=_("Approximate land area"),
help_text=_("The area of land covered by the project (in km²)")
)
# 1.5.2
land_ownership = models.CharField(
verbose_name=_("Land ownership"),
help_text=_("What type of ownership does the land fall under?"),
max_length=3,
choices=LAND_OWNERSHIP_CHOICES
)
# 1.5.3
land_ownership_details = models.CharField(
verbose_name=_("Land ownership details"),
help_text=_("Please specify details about land ownership if you chose 'other'"),
max_length=256,
null=True,
blank=True,
)
# 1.5.4
location_context = models.CharField(
verbose_name=_("Location"),
help_text=_("Select the context that is most applicable to this case\
study."),
max_length=3,
choices=LOCATION_CONTEXT_CHOICES
)
# 1.5.5
type_of_ecosystem = MultiSelectField(
verbose_name=_("Type(s) of ecosystem"),
help_text=_("Select the most relevant type(s)."),
max_length=56,
choices=TYPE_OF_ECOSYSTEM_CHOICES,
default=None,
null=True,
blank=True
)
# 1.5.5.3
describe_ecosystem = models.TextField(
verbose_name=_("Describe the ecosystem"),
help_text=_("In your own words, add more detail about the ecosystem."),
)
# Was 1.5.6; spec not being followed here after request from client
people_affected_indigenous = models.TextField(
verbose_name=_("Indigenous people affected"),
help_text=_("What group or groups of indigenous people are affected by this project? \
Please separate by newline."),
blank=True
)
people_affected_other = models.TextField(
verbose_name=_("Non-indigenous people affected"),
help_text=_("What other group or groups of people are affected by this project? \
Please separate by newline."),
blank=True
)
# 1.6
project_status = models.CharField(
verbose_name=_("Status of Project"),
help_text=_("What is the status of the current project?"),
max_length=6,
choices=PROJECT_STATUS_CHOICES
)
# 1.7
start_year = models.IntegerField(
verbose_name=_("Start year"),
help_text=_("Select the year the project was started. \
If the project hasn't begun, select the projected start year."),
choices=YEAR_CHOICES,
default=None,
null=True,
blank=True
)
# 1.8
completion_year = models.IntegerField(
verbose_name=_("Completion year"),
help_text=_("Select the year the project was completed. \
If the project hasn't finished, select the projected completion year."),
choices=YEAR_CHOICES,
default=None,
null=True,
blank=True
)
# 1.9
synopsis = models.TextField(
verbose_name=_("Synopsis"),
help_text=_("Briefly describe the project. This will be displayed at\
the top of the case study page. Maximum 500 chars (about \
3½ tweets)")
)
# 1.10
full_description = models.TextField(
verbose_name=_("Full Description"),
help_text=_("Describe the project in full. Separate paragraphs with a\
new line Please add as much detail as you feel is necessary\
here.")
)
# 1.11
project_owners = models.TextField(
verbose_name=_("Project and facility owners"),
help_text=_("List companies or organisations that own the project and/or facilities. Separate with a new line."),
blank=True
)
# 1.12
shareholders = models.TextField(
verbose_name=_("Shareholders of the project owners"),
help_text=_("List shareholders of the project owners you've just listed. Separate with a new line."),
blank=True
)
# 1.13.1
financial_institutions = MultiSelectField(
verbose_name=_("Financial institutions"),
help_text=_("Select any financial institutions that have or are considering extending \
loans or guarantees to the project."),
choices=FINANCIAL_INSTITUTIONS,
blank=True
)
# 1.13.2
financial_institutions_other = models.TextField(
verbose_name=_("Financial institutions other"),
help_text=_("List any other financial institutions not listed above. \
Put each on a new line."),
blank=True
)
# 1.14
energy_customers = models.TextField(
verbose_name=_("Energy consumers"),
help_text=_("List any wholesale energy customers that take energy from the development. E.g. 'national \
grids' or private energy suppliers. Please separate with a newline."),
blank=True
)
# 1.15.1
image = models.ImageField(
verbose_name=_("Image")
)
# 1.15.2
image_caption = models.CharField(
verbose_name=_("Image caption"),
max_length=240,
default=None,
null=True,
)
# 1.15.3
image_credit = models.CharField(
verbose_name=_("Image credit(s)"),
max_length=240,
default=None,
null=True,
)
# 1.16.1
video = models.URLField(
verbose_name=_("Video URL"),
help_text=_("Copy the URL to a YouTube or Vimeo video that relates to the case study."),
max_length=80,
validators=[validators.YouTubeOrVimeoValidator()],
blank=True
)
# 1.16.2
video_caption = models.CharField(
verbose_name=_("Video caption"),
max_length=240,
blank=True,
default=None,
null=True,
)
# 1.16.3
video_credit = models.CharField(
verbose_name=_("Video credit(s)"),
max_length=240,
blank=True,
default=None,
null=True,
)
# 1.17.1
media_coverage_mainstream = models.TextField(
verbose_name=_("Links to media reports"),
help_text=_("Provide any links to mainstream media coverage."),
default=None,
null=True,
)
# 1.17.2
media_coverage_independent = models.TextField(
verbose_name=_("Independent grassroots reports"),
help_text=_("Provide any links to grassroots/independent media coverage."),
default=None,
null=True,
)
# 1.18.1
community_voices = models.TextField(
verbose_name=_("Community Voices"),
help_text=_("Add any direct quotes from members of the community that \
relate to this project"),
default=None,
null=True,
blank=True
)
# 1.18.2
direct_comms = models.TextField(
verbose_name=_("Reports of direct communications"),
help_text=_("Add any reports of direct communication between community members and \
representatives of developers/companies/investors."),
default=None,
null=True,
blank=True
)
# 1.18.3
social_media_links = models.TextField(
verbose_name=_("Social media links"),
help_text=_("Add any links to social media accounts directly relating to the project."),
max_length=500,
default=None,
null=True,
blank=True
)
##
# Second Screen - Technical and economic analysis
##
# 2.1 - Renewable Energy Generation
# 2.1.1
generation_technology = models.CharField(
verbose_name=_("Generation technology"),
help_text=_("Select the type of renewable energy generation that most applies to this case study."),
max_length=4,
choices=GENERATION_TECHNOLOGY_CHOICES,
default=None,
null=True,
blank=True
)
# 2.1.1.12
# Should be filled in if 2.1.1 was answered as biogas or biomass.
biomass_detail = models.CharField(
verbose_name=_("Description of feedstock"),
help_text=_("If you selected biogas or biomass, please describe the feedstock (where the fuel came from e.g. \
corn, algae, anaerobic digestion, commercial waste etc)"),
max_length=200,
default=None,
null=True,
blank=True
)
# 2.1.1.14
generation_technology_other = models.CharField(
verbose_name=_("Other generation type"),
help_text=_("If you selected other, please specify the generation technology (e.g. tidal, wave etc)"),
max_length=200,
default=None,
null=True,
blank=True
)
# 2.1.2
total_generation_capacity = models.PositiveIntegerField(
verbose_name=_("Total generation capacity (in kW)"),
help_text=_("Please enter the total generation capacity of the project in kW"),
default=None,
null=True,
blank=True,
)
# 2.1.3
# TODO: Auto-completion based on previous entries so we can query case-studies with the same answer.
generation_equipment_supplier = models.TextField(
verbose_name=_("Generation equipment supplier"),
help_text=_("Enter the supplier of the generation equipment. (E.g. Siemens)"),
default=None,
null=True,
blank=True
)
# 2.1.4
total_investment = models.IntegerField(
verbose_name=_("Total investment (in USD)"),
help_text=_("The approximate total investment for the project in USD."),
default=None,
null=True,
blank=True
)
# 2.1.5
technical_or_economic_details = models.TextField(
verbose_name=_("Additional technical or economic details"),
help_text=_("Specify any additional technical or economic details relating to the project."),
blank=True
)
# 2.2 - Power Grids / Energy Storage
# 2.2.1
power_technology = models.CharField(
verbose_name=_("Power technology"),
help_text=_("Select the related energy technology."),
max_length=2,
choices=POWER_TECHNOLOGY_CHOICES,
default=None,
null=True,
blank=True
)
# 2.2.1.4
power_technology_other = models.CharField(
verbose_name=_("Other power technology"),
help_text=_("If you answered 'others', please specify the power technologies."),
max_length=128,
default=None,
null=True,
blank=True
)
# 2.2.2
energy_storage_capacity = models.DecimalField(
verbose_name=_("Energy storage capacity"),
help_text=_("Enter the total capacity of the energy storage system in kilowatt-hours (kWh)."),
max_digits=20,
decimal_places=3,
default=None,
null=True,
blank=True
)
# 2.2.2.1
maximum_power_output = models.DecimalField(
verbose_name=_('Maximum power output'),
help_text=_('Enter the maximum power output of the storage system in kilowatts (kW).'),
max_digits=12,
decimal_places=3,
default=None,
null=True,
blank=True
)
# 2.2.2.2
discharge_time = models.DecimalField(
verbose_name=_('Time for discharge from full capacity'),
help_text=_('Enter the time it takes to discharge from full capacity at maximum power output (in hours).'),
max_digits=6,
decimal_places=3,
default=None,
null=True,
blank=True
)
# 2.2.3
contractor_or_supplier_of_technology = models.CharField(
verbose_name=_('Contractor and/or supplier of technology'),
help_text=_('List companies that act as contractors or suppliers of technology related to energy storage.'),
max_length=256,
default=None,
null=True,
blank=True
)
# 2.2.4
approximate_total_investment = models.PositiveIntegerField(
verbose_name=_('Approximate total investment'),
help_text=_('Enter the approximate total investment in USD ($).'),
default=None,
null=True,
blank=True
)
# 2.2.5
additional_technical_details = models.CharField(
verbose_name=_("Additional technical or economic details"),
help_text=_("Add any additional details such as: length, from-to, voltage, substations etc"),
max_length=512,
default=None,
null=True,
blank=True
)
# 2.3.1.1
minerals_or_commodities = models.CharField(
verbose_name=_("Mineral commodity/commodities"),
help_text=_("Select the mineral commodity that is primarily mined in this project"),
max_length=3,
choices=MINERAL_COMMODITY_CHOICES,
default=None,
null=True,
blank=True
)
# 2.3.1.2
minerals_or_commodities_other = models.CharField(
verbose_name=_("Other mineral commodity"),
help_text=_("Enter the mineral commodity that isn't in the list."),
max_length=64,
default=None,
null=True,
blank=True
)
# 2.3.2
use_in_energy_economy = models.CharField(
verbose_name=_("Potential use in renewable energy economy"),
help_text=_("Select the potential use of the minerals in the renewable energy economy"),
max_length=3,
choices=USE_IN_ENERGY_ECONOMY_CHOICES,
default=None,
null=True,
blank=True
)
# 2.3.2.9
use_in_energy_economy_other = models.CharField(
verbose_name=_('Other use in energy economy'),
max_length=128,
default=None,
null=True,
blank=True
)
# 2.3.3.1
project_life_span = models.CharField(
verbose_name=_("Project life span"),
help_text=_("e.g. 12 years of production, 15 years overall"),
max_length=200,
blank=True
)
# 2.3.3.2
size_of_concessions = models.CharField(
verbose_name=_("Size of concessions"),
help_text=_("Describe the size of concession(s) granted to company/companies (e.g. 'one concession encompassing\
2,300 hectares')"),
max_length=200,
null=True,
default=None,
blank=True
)
# 2.3.3.3
projected_production_of_commodities = models.CharField(
verbose_name=_("Projected production of key commodities"),
help_text=_("Describe the projected production of commodities per annum and overall (e.g. '40 million tonnes of\
iron ore per year, 200 million tonnes over 5 year life of mine'"),
max_length=256,
default=None,
null=True,
blank=True
)
# 2.3.4
type_of_extraction = models.CharField(
verbose_name=_("Type of extraction"),
max_length=3,
choices=TYPE_OF_EXTRACTION_CHOICES,
default=None,
null=True,
blank=True
)
# 2.3.5
associated_infrastructure = models.CharField(
verbose_name=_("Associated infrastructure in the locality"),
help_text=_("List any associated infrastructure in the locality (e.g. tailings dams/mine waste storage and \
treatment facilities; ore processing facilities; smelting facilities; hydroelectric dams/energy infrastructure;\
transport infrastructure e.g. roads or rail."),
max_length=256,
default=None,
null=True,
blank=True
)
##
# Third Screen - Socio-economic analysis
##
# 3.1.1
positive_case_type = models.CharField(
verbose_name=_('What kind of positive case is this entry about?'),
help_text=_('Select the most relevant type of positive case'),
choices=POSITIVE_CASE_TYPE_CHOICES,
max_length=4,
default=None,
null=True,
blank=True,
)
# 3.1.2
socioeconomic_benefits = models.TextField(
verbose_name=_('Socio-economic benefits'),
help_text=_('Please expand on your response given in the full description on page one. We would expect \
benefits to go beyond emissions savings, paying rent for land, or complying with environmental or social \
legislation'),
default=None,
null=True,
blank=True
)
# 3.1.3 + 3.2.5
key_actors_involved = models.TextField(
verbose_name=_('Key actors involved (individual/organisational)'),
blank=True, null=True
)
# 3.1.4
project_status_detail = models.TextField(
verbose_name=_('Current status of the project'),
help_text=_("Describe the current status of the project, expanding beyond 'existing', 'under construction' etc"),
default=None,
null=True,
blank=True
)
# 3.1.5
obstacles_and_hindrances = models.CharField(
verbose_name=_('Obstacles and hindrances'),
help_text=_('List any obstacles or hindrances experienced in the course of the project'),
max_length=512,
default=None,
null=True,
blank=True
)
# 3.1.6
identified_partnerships = models.CharField(
verbose_name=_('Identified partnerships'),
help_text=_('Are you looking for partnerships or have any clearly identified need? If so, please describe it \
here.'),
max_length=256,
default=None,
null=True,
blank=True
)
# 3.1.7.1 + 3.2.8.1
contact_email = models.EmailField(
verbose_name=_('Email address'),
blank=True
)
# 3.1.7.2 + 3.2.8.1
contact_phone = PhoneNumberField(
verbose_name=_('Phone number'),
help_text=_('Please include the international prefix, beginning with "+".'),
blank=True
)
# 3.1.7.3 + 3.2.8.1
contact_website = models.URLField(
verbose_name=_('Website'),
blank=True
)
# 3.1.7.4 + 3.2.8.1
contact_twitter = models.CharField(
verbose_name=_('Twitter username'),
max_length=50,
blank=True
)
# 3.1.7.5 + 3.2.8.1
contact_facebook = models.URLField(
verbose_name=_('Facebook page'),
blank=True
)
# 3.1.7.6 + 3.2.8.1
contact_other = models.TextField(
verbose_name=_('Other contact details'),
blank=True
)
# 3.2.1
negative_case_reasons = MultiSelectField(
verbose_name=("Reasons this is a negative case study"),
choices=NEGATIVE_CASE_REASONS_CHOICES,
default=None,
null=True,
blank=True
)
# 3.2.1.9
negative_case_reasons_other = models.CharField(
verbose_name=_("Other reason for negative case"),
help_text=_("Please include other reasons, noting that we aim to focus on projects with substantive negative \
impacts on vulnerable groups."),
max_length=512,
default=None,
null=True,
blank=True
)
# 3.2.2
negative_socioenvironmental_impacts = models.TextField(
verbose_name=_("Describe the negative socio-environmental impacts"),
help_text=_("Provide a detailed description of the negative socio-environmental impacts (please provide all \
relevant details, such as type of ecosystem and presence of any existing reserve in the area, \
, specific communities affected by the project, total geographic footprint of the project, and \
tenure system affected in the case of land grabs, kind of permits that were irregularly issued if \
this is the case."),
default=None,
null=True,
blank=True
)
# 3.2.3
isolated_or_widespread = models.TextField(
verbose_name=_("Describe if the project is isolated or commonplace."),
help_text=_("Is this an isolated project or are there similar projects in the same geographic area? If there \
are more, can you describe them? Are there any significant cumulative synergistic effects?"),
default=None,
null=True,
blank=True
)
# 3.2.4.1
when_did_organising_start = models.CharField(
verbose_name=_("When did local organising efforts begin?"),
help_text=_("Before the project started? During project implementation? After project implementation? \
Describe in your own words."),
max_length=512,
default=None,
null=True,
blank=True
)
# 3.2.4.2
who_has_been_involved = models.TextField(
verbose_name=_("Which communities, groups and organisations have been involved?"),
blank=True, null=True
)
# 3.2.4.3
participation_mechanisms = models.TextField(
verbose_name=_("What mechanisms of participation have been used?"),
help_text=_("e.g. direct action, local referendums, legal cases, letters or petitions etc"),
blank=True
)
# 3.2.6
potential_partnerships = models.CharField(
verbose_name=_("Describe potential partnerships"),
help_text=_("Are you looking for partnerships or do you have any clearly identified need? If so, please \
describe it here."),
max_length=512,
default=None,
null=True,
blank=True
)
# 3.2.7
wants_conversation_with_ojuso = models.BooleanField(
verbose_name=_("Would you like to have a conversation with the ojuso team?"),
help_text=_("This would be a conversation about challenging or engaging related developers, companies and \
investors."),
default=True
)
##
# Fourth Screen - Uploads
##
# 4.1
official_project_documents = models.ManyToManyField(
'files.File',
related_name='official_project_document_for',
verbose_name=_("Official project documents"),
help_text=_("Attach any legal or official documents that relate to the project."),
blank=True,
)
# 4.2
other_documents = models.ManyToManyField(
'files.File',
related_name='other_document_for',
verbose_name=_("Other documents"),
help_text=_("Attach any other documents that relate to the project."),
blank=True,
)
# 4.3.1
shapefiles = models.ManyToManyField(
'files.File',
related_name='shapefile_for',
verbose_name=_("Shapefiles"),
help_text=_("If you have territory that you would like to show in relation to this project - e.g. Bienes \
Comunales de Ixtepec etc. This is a set of 3 or more (often 5-6) files with file extensions like \
.cpg, .dbf, .prj, .qpj, .shp, .shx"),
blank=True
)
# 4.3.2
coordinate_reference_system = models.ForeignKey(
SpatialRefSys,
null=True,
blank=True,
default=4326
)
# 4.3.3
name_of_territory_or_area = models.CharField(
verbose_name=_("Name of territory or area"),
max_length=512,
default=None,
null=True,
blank=True
)
# 4.4
shown_on_other_platforms = models.BooleanField(
verbose_name=_("Is this case study shown on other platforms?"),
default=True
)
# 4.4.1
shown_on_other_platforms_detail = models.TextField(
verbose_name=_("Shown on other platforms - Detail"),
help_text=_("Please provide links to other places the case study appears."),
blank=True
)
objects = CaseStudyQuerySet.as_manager()
def __str__(self):
"""The String representation of the case study. (Entry name with country name.)"""
return "%s in %s" % (self.entry_name, self.country.name)
def clean(self, *args, **kwargs):
"""Perform validation on the model as a whole and throw a ValidationError if anything isn't how it should be."""
pass
def save(self, *args, **kwargs):
"""Override the save method to create a slug when the model is created. Slug is only created and never modified
as we are basing our URLs on it and don't want it to change - ever."""
if not self.pk:
# Newly created object, so set slug
self.slug = slugify(self.entry_name)
# Continue normal save method by calling original save method.
super(CaseStudy, self).save(*args, **kwargs)
def is_video_youtube(self):
return self.video.count("youtube.com") > 0
def get_youtube_id(self):
"""Gets the 11 character YouTube video ID from the video field."""
return parse.parse_qs(parse.urlparse(self.video).query)["v"][0]
def is_video_vimeo(self):
return self.video.count("vimeo.com") > 0
def get_vimeo_id(self):
"""Gets the 11 number video ID from the video field."""
return parse.urlparse(self.video).path
def get_negative_case_reasons_no_other(self):
"""Return a list of negative case reasons, minus the 'other' choice (if selected)"""
choices = self.get_negative_case_reasons_list()
if choices.count(self.NEGATIVE_CASE_REASONS_OTHER_TEXT) > 0:
choices.remove(self.NEGATIVE_CASE_REASONS_OTHER_TEXT)
return choices
def get_renewable_generation_detail(self):
"""Prepend appropriate descriptive text when accessing renewable generation type."""
if self.generation_technology:
if self.generation_technology.endswith('WE'):
return _('Wind energy') + " " + self.get_generation_technology_display()
elif self.generation_technology.endswith('PV'):
return _('Photovoltaic electricity') + " " + self.get_generation_technology_display()
elif self.generation_technology.endswith('HYD'):
return _('Hydroelectric') + " " + self.get_generation_technology_display()
elif self.generation_technology == 'OTHR':
return self.generation_technology_other
else:
return self.get_generation_technology_display()
else:
return ""
class Meta:
verbose_name_plural = 'case studies'