import datetime from urllib import parse from django.contrib.gis.db import models from django.contrib.auth.models import User from django_extensions.db.fields import AutoSlugField from django_countries.fields import CountryField from django.utils.translation import ugettext as _ from django.template.defaultfilters import slugify from . import validators class CaseStudy(models.Model): """Model for case studies submitted to the Ojuso Platform""" # Choice lists for drop-downs SECTOR_CHOICES = ( (_('Renewable Energy Generation'), ( ('WND', _('Wind')), ('SOL', _('Solar')), ('HYD', _('Hydro')), )), ('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')), ) TYPE_OF_ECOSYSTEM_CHOICES = ( (_('Water Based'), ( ('MARINE', _('Marine (e.g. Ocean, Sea)')), ('FRESH', _('Freshwater (e.g. Freshwater, Lake)')), )), (_('Land Based'), ( ('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')), ) 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')) ) # 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 # TODO: Change this so it's not dynamic. Slugs should never change. slug = AutoSlugField(populate_from=['entry_name']) ## # First Screen ## # 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"), help_text=_("Place a marker using the tools on the left of the map. Zoom in as far as you can so the placement \ is accurate (important)") ) # 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 field"), 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 = models.CharField( verbose_name=_("Type of ecosystem"), help_text=_("Select the most relevant type of ecosystem."), max_length=6, choices=TYPE_OF_ECOSYSTEM_CHOICES, ) # 1.5.5.3 describe_ecosystem = models.CharField( verbose_name=_("Describe the ecosystem"), help_text=_("In your own words, add more detail about the ecosystem."), max_length=256, ) # 1.5.6 affects_indigenous = models.BooleanField( verbose_name=_("Affects indigenous people?"), help_text=_("Does the project affect indigenous communities?") ) # 1.5.6.1 affects_indigenous_detail = models.CharField( verbose_name=_("Affects Indigenous - Details"), help_text=_("What group of indigenous people does the community belong\ to?"), max_length=256, default=None, null=True, 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)"), max_length=500 ) # 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.CharField( verbose_name=_("Project and facility owners"), help_text=_("List companies or organisations that own the project and/or facilities. Separate with a comma."), max_length=120, default=None, null=True, blank=True ) # 1.12 shareholders = models.CharField( verbose_name=_("Shareholders of the project owners"), help_text=_("List shareholders of the project owners you've just listed. Separate with a comma."), max_length=120, default=None, null=True, blank=True ) # 1.13 financial_institutions = models.CharField( verbose_name=_("Financial institutions"), help_text=_("List banks and other financial institutions that have or are considering extending loans \ or guarantees to the project. Separate with a comma."), max_length=120, default=None, null=True, blank=True ) # 1.14 energy_customers = models.CharField( 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."), max_length=120, default=None, null=True, blank=True ) # 1.15.1 image = models.ImageField( verbose_name=_("Image") ) # 1.15.2 image_caption = models.CharField( verbose_name=_("Image caption"), max_length=500, default=None, null=True, ) # 1.15.3 image_credit = models.CharField( verbose_name=_("Image credit(s)"), max_length=200, default=None, null=True, ) # 1.16.1 video = models.URLField( verbose_name=_("YouTube Video"), help_text=_("Copy the URL to a related YouTube™ video that relates to the case study."), max_length=43, validators=[validators.YoutubeURLValidator()] ) # 1.16.2 video_caption = models.CharField( verbose_name=_("Video caption"), max_length=500, default=None, null=True, ) # 1.16.3 video_credit = models.CharField( verbose_name=_("Video credit(s)"), max_length=500, 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."), max_length=500, 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."), max_length=500, 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") ) # 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."), max_length=500, default=None, null=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 ## # 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=_("Generation technology detail"), 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 - autocomplete_light queryset # 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.CharField( verbose_name=_("Additional technical or economic details"), help_text=_("Specify any additional technical or economic details relating to the project."), max_length=500, default=None, null=True, blank=True ) # 2.2 - Only if 1.2.2 selected # 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 ) 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 ) energy_storage_capacity = models.IntegerField( verbose_name=_("Energy storage capacity"), help_text=_("Enter the total capacity of the energy storage system."), default=None, null=True, blank=True ) ## # Third Screen ## ## # Fourth Screen ## # 4.1 official_project_documents = models.FileField( verbose_name=_("Official project documents"), help_text=_("Attach any legal or official documents that relate to the project."), default=None, null=True, blank=True ) # 4.2 other_documents = models.FileField( verbose_name=_("Other documents"), help_text=_("Attach any other documents that relate to the project."), default=None, null=True, blank=True ) # 4.3 definition_of_affected_territories = models.CharField( verbose_name=_("Definition of affected territories"), help_text=_("In your own words, define the territories that the project will affect."), max_length=512, default=None, null=True, blank=True ) # 4.4 shown_on_other_platforms = models.NullBooleanField( verbose_name=_("Show on other platforms?"), help_text=_("Tick the box if you would like us to show this case study on other social media platforms"), default=None, null=True, blank=True ) # 4.4.1 shown_on_other_platforms_detail = models.CharField( verbose_name=_("Show on other platforms - Detail"), help_text=_("List the social media platforms that you would like us to specifically publish the case study on"), max_length=128, null=True, blank=True ) 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 get_video_id(self): """Gets the 11 character YouTube video ID from the video field.""" return parse.parse_qs(parse.urlparse(self.video).query)["v"][0]