class NewsStory(models.Model): headline = models.CharField(max_length=512) short_story = models.TextField() text = MarkdownField(rendered_field="text_rendered", validator=VALIDATOR_STANDARD) text_rendered = RenderedMarkdownField() created = models.DateTimeField(auto_now_add=True) modified = models.DateTimeField(auto_now=True) published = models.BooleanField(default=False) url = models.URLField(blank=True, null=True) @property def url_read_more(self): if self.url: return self.url return reverse("news:story", kwargs={"pk": self.pk}) def __str__(self): return self.headline class Meta: ordering = ("-created", ) verbose_name = _("News story") verbose_name_plural = _("News stories")
class Page(models.Model): title = models.CharField(max_length=100, help_text="100 characters or fewer.") subtitle = models.CharField( max_length=100, blank=True, default='', help_text="100 characters or fewer. Optional." ) modified = models.DateTimeField(auto_now=True, verbose_name="date modified") slug = models.SlugField( unique=True, help_text="Changing this value after initial creation will break existing " "page URLs. Must be unique.", ) body = MarkdownField(rendered_field='body_rendered', validator=VALIDATOR_CLASSY) body_rendered = RenderedMarkdownField() def __str__(self): return self.title def get_absolute_url(self): return reverse('content:page', kwargs={'slug': self.slug}) class Meta: verbose_name = "page" verbose_name_plural = "pages"
class Post(PublishedModel): title = models.CharField(max_length=100, help_text="100 characters or fewer.") slug = models.SlugField(unique=True, help_text="Changing this value after initial creation will break existing " "post URLs. Must be unique.") tags = TaggableManager(blank=True) allow_comments = models.BooleanField(default=True) author = models.CharField(max_length=50, help_text="50 characters or fewer.") created = models.DateTimeField(auto_now_add=True, verbose_name="date created") modified = models.DateTimeField(auto_now=True, verbose_name="date modified") image = VersatileImageField(upload_to='blog', blank=True, null=True, ppoi_field='image_ppoi') image_ppoi = PPOIField() description = models.TextField(max_length=140, blank=True, help_text="140 characters or fewer.") text = MarkdownField(rendered_field='text_rendered', validator=VALIDATOR_CLASSY) text_rendered = RenderedMarkdownField() class Meta: ordering = ['-created'] def __str__(self): return self.title def get_absolute_url(self): return reverse('blog:detail', kwargs={'slug': self.slug}) @cached_property def structured_data(self): url = settings.SITE_URL + self.get_absolute_url() data = { '@type': 'BlogPosting', 'headline': self.title, 'description': self.description or Truncator(strip_tags(self.text_rendered)).chars(200), 'author': { '@type': 'Person', 'name': self.author }, 'datePublished': self.created.strftime('%Y-%m-%d'), 'dateModified': self.modified.strftime('%Y-%m-%d'), 'publisher': None, 'url': url, 'mainEntityOfPage': { '@type': 'WebPage', '@id': url }, } if self.image: data['image'] = { '@type': 'ImageObject', 'url': settings.SITE_URL + self.image.url, 'height': self.image.height, 'width': self.image.width } return data
class PrimaryEffect(models.Model): """ The Primary Effect model holds data for effects of Project Activities that are classified as Primary """ # IDENTIFICATION primary_effect_identifier = models.CharField( max_length=80, blank=True, null=True, help_text='A unique identification of a Primary Effect internal use') primary_effect_description = MarkdownField( blank=True, null=True, rendered_field='text_rendered', validator=VALIDATOR_STANDARD, help_text= 'Textual description of a Primary Effect. Markdown format is supported <a class="risk_manual_url" href="https://www.openriskmanual.org/wiki/Primary_GHG_Effects">Documentation</a>' ) # text = MarkdownField(rendered_field='text_rendered', validator=VALIDATOR_STANDARD) text_rendered = RenderedMarkdownField(blank=True, null=True) # LINKS project_activity = models.ForeignKey( 'ProjectActivity', blank=True, null=True, on_delete=models.CASCADE, help_text="The Project Activity to which this Primary Effect belongs") effect_category = models.IntegerField( blank=True, null=True, choices=PRIMARY_GHG_EFFECTS, help_text= 'The general category to which the Primary Effect belongs <a class="risk_manual_url" href="https://www.openriskmanual.org/wiki/Primary_GHG_Effects">Documentation</a>' ) # # BOOKKEEPING FIELDS # creation_date = models.DateTimeField(auto_now_add=True) last_change_date = models.DateTimeField(auto_now=True) def __str__(self): return self.primary_effect_identifier def get_absolute_url(self): return reverse('portfolio:PrimaryEffect_edit', kwargs={'pk': self.pk}) class Meta: verbose_name = "Primary Effect" verbose_name_plural = "Primary Effects"
class Location(models.Model): slug = AutoSlugField( always_update=True, # slugify=lambda v: ''.join( # [l for l in v # .replace('æ','ae').replace('ø','oe').replace('å','aa') # .lower() if l.isalpha() or l == " " # ]).replace(" ", '-'), populate_from='name', unique_with=('municipality') #, 'county') ) ssr_id = models.PositiveIntegerField(blank=True, null=True, unique=True, verbose_name="SSR ID") name_types = models.ManyToManyField(NameType) name = models.CharField(max_length=150) municipality = models.ForeignKey(Municipality, null=True, on_delete=models.SET_NULL) place = models.CharField(max_length=150, null=True, blank=True) # description = models.TextField(max_length=1000, null=True, blank=True) description_md = MarkdownField( max_length=1500, null=True, blank=True, use_editor=False, use_admin_editor=False, rendered_field='description', # validator=MARKDOWN_VALIDATOR, ) description = RenderedMarkdownField(null=True, blank=True) geometry = models.PolygonField() created_at = models.DateTimeField(auto_now_add=True) @property def county(self): return self.municipality.get_county_display() @property def full_address(self): if self.place: return "{}, {}, {}".format(self.name, self.place, self.municipality.name) return "{}, {}".format(self.name, self.municipality.name) class Meta: ordering = ('name', ) def __str__(self): return f"{self.full_address}" # [{self.name_type.name}]"
class Project(models.Model): category = models.ForeignKey(Category, related_name='projects', on_delete=models.CASCADE) user = models.ForeignKey(User, related_name='projects', on_delete=models.CASCADE) name = models.CharField(max_length=200, db_index=True) slug = models.SlugField(max_length=200, db_index=True) tags = TaggableManager() description = MarkdownField(rendered_field='description_rendered', validator=VALIDATOR_STANDARD, blank=True) description_rendered = RenderedMarkdownField() video = models.URLField(blank=True) goal = models.DecimalField(max_digits=10, decimal_places=2) collected_sum = models.DecimalField(max_digits=10, decimal_places=2, default=0) expiration_date = models.DateField() created = models.DateTimeField(auto_now_add=True) updated = models.DateTimeField(auto_now=True) backers = models.PositiveIntegerField(default=0) rate = models.FloatField( validators=[MinValueValidator(0), MaxValueValidator(5)], default=0) class Meta: ordering = ('name', ) index_together = (('id', 'slug'), ) def __str__(self): return self.name def get_absolute_url(self): return reverse('project', args=[self.slug, self.id]) def save(self, *args, **kwargs): self.slug = slugify(self.name) self.video = self.video.replace('youtu.be', 'www.youtube.com/embed').replace( 'watch?v=', 'embed/') super(Project, self).save(*args, **kwargs) def delete(self, *args, **kwargs): super(Project, self).delete(*args, **kwargs) Tag.objects.annotate(ntag=Count('taggit_taggeditem_items')).filter( ntag=0).delete() def days_left(self): return (self.expiration_date - date.today()).days
class Production(models.Model): type = models.CharField(max_length=4, choices=PRODUCTION_TYPES) slug = AutoSlugField(always_update=True, populate_from='title', unique_with=('type', )) title = models.CharField(max_length=50) release_date = models.DateField('Released') poster = ImageField(upload_to=PathAndRename('posters/'), blank=True, null=True) summary_md = MarkdownField(max_length=1000, null=True, blank=True, rendered_field='summary') summary = RenderedMarkdownField(null=True, blank=True) runtime = models.PositiveIntegerField(null=True, blank=True) tmdb_id = models.CharField(max_length=10, null=True, blank=True, unique=True, verbose_name="TMDb ID") imdb_id = models.CharField(max_length=10, null=True, blank=True, unique=True, verbose_name="IMDb ID") nbdb_id = models.CharField(max_length=10, null=True, blank=True, unique=True, verbose_name="NBDb ID") crew = models.ManyToManyField(Person, through='people.Job') locations = models.ManyToManyField('locations.Location', through='productions.Scene') created_at = models.DateTimeField(auto_now_add=True) @property def year(self): return self.release_date.year class Meta: ordering = ('title', ) def __str__(self): return f"{self.title} ({self.year})"
class Migration(migrations.Migration): initial = True dependencies = [ ('taggit', '0003_taggeditem_add_unique_index'), ] operations = [ migrations.CreateModel( name='Event', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('title', models.CharField(help_text='100 characters or fewer.', max_length=100)), ('where', models.CharField(max_length=200)), ('what', MarkdownField(rendered_field='what_rendered')), ('what_rendered', RenderedMarkdownField()), ('start', models.DateTimeField()), ('end', models.DateTimeField()), ('created', models.DateTimeField(auto_now_add=True, verbose_name='date created')), ('modified', models.DateTimeField(auto_now=True, verbose_name='date modified')), ('image', versatileimagefield.fields.VersatileImageField( blank=True, null=True, upload_to='events')), ('image_ppoi', versatileimagefield.fields.PPOIField(default='0.5x0.5', editable=False, max_length=20)), ('tags', taggit.managers.TaggableManager( blank=True, help_text='A comma-separated list of tags.', through='taggit.TaggedItem', to='taggit.Tag', verbose_name='Tags')), ], ), ]
class BlogPost(models.Model): """the post data""" user_profile = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE) title = models.CharField(max_length=100) autor = models.CharField(max_length=35) is_featured = models.BooleanField(default=False) date_published = models.DateTimeField(default=timezone.now) # body = models.CharField(max_length=6000) body = MarkdownField(rendered_field='text_rendered', validator=VALIDATOR_STANDARD) image_link = models.CharField(max_length=200) description = models.CharField(max_length=1000) text_rendered = RenderedMarkdownField() def __str__(self): """return the post title as string""" return self.title
class Migration(migrations.Migration): dependencies = [ ('foxtail_blog', '0005_comment_length'), ] operations = [ migrations.AlterField( model_name='post', name='text_rendered', field=RenderedMarkdownField(), ), migrations.AlterField( model_name='post', name='text', field=MarkdownField(rendered_field='text_rendered'), ), ]
class News(models.Model): project = models.ForeignKey(Project, on_delete=models.CASCADE, related_name='news') title = models.CharField(max_length=200, db_index=True) text = MarkdownField(rendered_field='text_rendered', validator=VALIDATOR_STANDARD, blank=True) text_rendered = RenderedMarkdownField() image = CloudinaryField('image', null=True, blank=True) created = models.DateTimeField(auto_now_add=True) class Meta: ordering = ('-created', ) verbose_name = 'news' verbose_name_plural = 'news' def get_absolute_url(self): return reverse('news', args=[self.id])
class Scene(models.Model): production = models.ForeignKey(Production, on_delete=models.CASCADE) description_md = MarkdownField(max_length=800, null=True, blank=True, rendered_field='description') description = RenderedMarkdownField(null=True, blank=True) location = models.ForeignKey('locations.Location', blank=True, null=True, on_delete=models.SET_NULL) @property def is_unidentified(self): return True if not self.location else False def __str__(self): return '{}: {}'.format( self.production.title, self.location.full_address if self.location else '(None)')
class Research(models.Model): scenes = models.ManyToManyField(Scene, limit_choices_to={'location': None}, related_name='research') best_guess = models.CharField(max_length=50) description_md = MarkdownField( max_length=1500, null=True, blank=True, use_editor=False, use_admin_editor=False, rendered_field='description', ) description = RenderedMarkdownField(null=True, blank=True) geometry = models.PointField(blank=True, null=True) @property def scene_count(self): return self.scenes.count() class Meta: verbose_name_plural = 'research'
class Batch(BuskerModel): """ Represents a batch of Download codes generated for a given DownloadableWork object. """ label = models.CharField(max_length=255) work = models.ForeignKey(DownloadableWork, on_delete=models.CASCADE) private_note = models.TextField( null=True, blank=True, help_text="Optional note for private use; will not be " "displayed to end users.") public_message = MarkdownField( null=True, blank=True, validator=VALIDATOR_STANDARD, rendered_field='public_message_rendered', help_text= "Optional markdown-formatted message that will be displayed on the " "download page.") public_message_rendered = RenderedMarkdownField() number_of_codes = models.IntegerField( help_text= "The number of Download Codes to be generated with this batch. " "(Additional codes may be added to the batch later.)", default=100) # TODO place an upper limit? max_uses = models.IntegerField( help_text= "The number of times this code can be used. (You may subsequently change " "this amount on individual codes, but this will be used as the initial " "value.) " "(0 = unlimited)", default=3) def __str__(self): return f"{self.label} -- {self.work.title} by {self.work.artist.name}" class Meta: verbose_name_plural = "Batches" ordering = ('-created_date', 'work__artist__name', 'work__title')
class ActivityBarrier(models.Model): """ The Activity Barrier model holds data for barriers to Project Activities """ # IDENTIFICATION barrier_identifier = models.CharField(max_length=80, blank=True, null=True, help_text='A unique identification of a Barrier') barrier_description = MarkdownField(blank=True, null=True, rendered_field='text_rendered', validator=VALIDATOR_STANDARD, help_text='Textual description of an Activity Barrier. Markdown format is supported <a class="risk_manual_url" href="https://www.openriskmanual.org/wiki/">Documentation</a>') text_rendered = RenderedMarkdownField() # LINKS project_activity = models.ForeignKey(ProjectActivity, blank=True, null=True, on_delete=models.CASCADE, help_text="The Project Activity to which this Primary Effect belongs") # # BOOKKEEPING FIELDS # creation_date = models.DateTimeField(auto_now_add=True) last_change_date = models.DateTimeField(auto_now=True) def __str__(self): return self.barrier_identifier def get_absolute_url(self): return reverse('risk:ActivityBarrier_edit', kwargs={'pk': self.pk}) class Meta: verbose_name = "Activity Barrier" verbose_name_plural = "Activity Barrier"
class Event(models.Model): title = models.CharField(max_length=100, help_text="100 characters or fewer.") slug = AutoSlugField(populate_from='title', unique_for_year='start') tags = TaggableManager(blank=True) description = MarkdownField(rendered_field='description_rendered', validator=VALIDATOR_CLASSY) description_rendered = RenderedMarkdownField() url = models.URLField(blank=True) location = models.CharField(max_length=200) address = models.TextField(blank=True) start = models.DateField() start_time = models.TimeField(null=True, blank=True, help_text="Time is optional.") end = models.DateField(null=True, blank=True, help_text="End date and time are optional.") end_time = models.TimeField(null=True, blank=True, help_text="End date and time are optional.") image = VersatileImageField(upload_to='events', blank=True, null=True, ppoi_field='image_ppoi') image_ppoi = PPOIField() created = models.DateTimeField(auto_now_add=True, verbose_name="date created") modified = models.DateTimeField(auto_now=True, verbose_name="date modified") class Meta: ordering = ["start"] def __str__(self): return self.title def get_absolute_url(self): return reverse('events:detail', kwargs={ 'year': self.start.year, 'slug': self.slug }) @property def is_ended(self): if self.end: end = datetime.combine(self.end, self.end_time) if self.end_time else\ datetime.combine(self.end, datetime.min.time(), tzinfo=utc) else: end = datetime.combine( self.start, self.end_time) if self.end_time else (self.start + timedelta(days=1)) return end < now() @cached_property def structured_data(self): url = settings.SITE_URL + self.get_absolute_url() data = { '@type': 'Event', 'name': self.title, 'description': self.description or Truncator(strip_tags(self.description_rendered)).chars(200), 'startDate': self.start.strftime('%Y-%m-%d'), 'url': url, 'mainEntityOfPage': { '@type': 'WebPage', '@id': url }, } if self.end: data['endDate'] = self.end.strftime('%Y-%m-%d') if self.location: data['location'] = { '@type': 'Place', 'name': self.location, 'address': self.address or self.location, } if self.image: data['image'] = { '@type': 'ImageObject', 'url': self.image.url, 'height': self.image.height, 'width': self.image.width } return data
class ProjectActivity(models.Model): """ The Project Activity model holds data for specific sustainability activities associated with a Project. The model acts as a container for both target activities and potentially alternative "baseline candidates" A Project will have at least one Project Activity project_activity_identifier varchar(80), project_activity_description text, -> SHORT_DESCR project_activity_emissions real, baseline_activity_emissions real, project_activity_role integer, baseline_estimation integer, baseline_procedure_justification text, references portfolio_project NEW project_activity_title NEW region NEW main_site """ # IDENTIFICATION project_activity_identifier = models.CharField( max_length=80, blank=True, null=True, help_text= 'A unique identification of a Project Activity for internal use') project_activity_title = models.CharField( max_length=160, blank=True, null=True, help_text='The title of the project activity') project_activity_description = MarkdownField( blank=True, null=True, rendered_field='text_rendered', validator=VALIDATOR_STANDARD, help_text= 'Textual description of a Project Activity. Markdown format is supported <a class="risk_manual_url" href="https://www.openriskmanual.org/wiki/GHG_Project_Activity">Documentation</a>' ) text_rendered = RenderedMarkdownField() # LINKS project = models.ForeignKey( 'Project', blank=True, null=True, on_delete=models.CASCADE, help_text="The Project to which this Activity belongs") # PROJECT ACTIVITY DATA region = models.CharField( max_length=10, null=True, blank=True, help_text= 'NUTS Code of Region. <a class="risk_manual_url" href="https://www.openriskmanual.org/wiki">Documentation</a>' ) main_site = models.CharField( max_length=160, blank=True, null=True, help_text='The main site of the project activity (if applicable)') project_activity_emissions = models.FloatField( blank=True, null=True, help_text="Emissions expressed in t CO2 eq/year") baseline_activity_emissions = models.FloatField( blank=True, null=True, help_text="Emissions expressed in t CO2 eq/year") project_activity_role = models.IntegerField( blank=True, null=True, choices=PROJECT_ACTIVITY_ROLE, help_text='Select whether the activity role is baseline or target') baseline_estimation = models.IntegerField( blank=True, null=True, choices=BASELINE_ESTIMATION_PROCEDURE, help_text= 'Baseline procedures are methods used to estimate baseline emissions <a class="risk_manual_url" href="https://www.openriskmanual.org/wiki/Baseline_Emissions">Documentation</a>' ) baseline_procedure_justification = MarkdownField( blank=True, null=True, rendered_field='text_rendered2', validator=VALIDATOR_STANDARD, help_text= 'Justification of the Baseline Estimation Procedure selected <a class="risk_manual_url" href="https://www.openriskmanual.org/wiki/Baseline_Emissions">Documentation</a>' ) # text = MarkdownField(rendered_field='text_rendered', validator=VALIDATOR_STANDARD) text_rendered2 = RenderedMarkdownField() # # BOOKKEEPING FIELDS # creation_date = models.DateTimeField(auto_now_add=True) last_change_date = models.DateTimeField(auto_now=True) def __str__(self): return self.project_activity_identifier def get_absolute_url(self): return reverse('portfolio:ProjectActivity_edit', kwargs={'pk': self.pk}) class Meta: verbose_name = "Project Activity" verbose_name_plural = "Project Activities"
class Project(models.Model): """ The Project model holds data for a general sustainability Project (irrespective of financial attributes) """ # TODO Project Status # IDENTIFICATION project_identifier = models.CharField(max_length=80, blank=True, null=True, help_text='A unique identification of the Project for internal use') project_title = models.CharField(max_length=160, blank=True, null=True, help_text='The title of the project') project_reference = models.CharField(max_length=160, blank=True, null=True, help_text='Manager reference for the project') # LINKS project_category = models.ForeignKey('ProjectCategory', blank=True, null=True, on_delete=models.SET_NULL, help_text="The project category to which this project is best classified") portfolio = models.ForeignKey('ProjectPortfolio', blank=True, null=True, on_delete=models.CASCADE, help_text="The portfolio to which this project belongs") # PROJECT DATA project_description = MarkdownField(blank=True, null=True, rendered_field='text_rendered', validator=VALIDATOR_STANDARD, help_text='Textual description of a Project. Markdown format is supported <a class="risk_manual_url" href="https://www.openriskmanual.org/wiki/GHG_Project">Documentation</a>') # text = MarkdownField(rendered_field='text_rendered', validator=VALIDATOR_STANDARD) text_rendered = RenderedMarkdownField() cpv_code = models.CharField(max_length=20, blank=True, null=True, help_text="The Common Procurement Vocabulary Code") project_budget = models.IntegerField(blank=True, null=True, help_text="The Project Budget") project_currency = models.CharField(max_length=4, blank=True, null=True, help_text="The currency code in which the project is accounted for") # PROJECT SCORECARD DATA design_and_technology_risk = models.IntegerField(blank=True, null=True, choices=DESIGN_AND_TECHNOLOGY_RISK_CHOICES, help_text='Risk Factor. EBA 3.1. <a class="risk_manual_url" href="https://www.openriskmanual.org/wiki/Technology_Risk">Documentation</a>') completion_risk = models.IntegerField(blank=True, null=True, choices=COMPLETION_RISK_CHOICES, help_text='Risk SubFactor. EBA 3.2.3. <a class="risk_manual_url" href="https://www.openriskmanual.org/wiki">Documentation</a>') # OTHER construction_risk = models.FloatField(blank=True, null=True, help_text='Standard Description. <a class="risk_manual_url" href="https://www.openriskmanual.org/wiki">Documentation</a>') project_visualization = models.ImageField(upload_to='project_files', blank=True, null=True, help_text='Visual representation of a Project') # # BOOKKEEPING FIELDS # creation_date = models.DateTimeField(auto_now_add=True) last_change_date = models.DateTimeField(auto_now=True) def __str__(self): return self.project_identifier def get_absolute_url(self): return reverse('portfolio:Project_edit', kwargs={'pk': self.pk}) class Meta: verbose_name = "Project" verbose_name_plural = "Projects"