Files
fet2020/fet2020/posts/models.py
2020-10-24 16:24:40 +00:00

302 lines
9.3 KiB
Python

from django.contrib.auth.models import User
from django.core.validators import ValidationError
from django.db import models
from django.urls import reverse
from django.utils import timezone
from django.utils.text import slugify
from django.utils.translation import gettext_lazy as _
from taggit.managers import TaggableManager
from documents.api import getPadHTML, setPadHTML, createPadifNotExists
from .managers import (
PostManager, ArticleManager, NewsManager, AllEventManager, EventManager, FetMeetingManager
)
import re
from datetime import timedelta
import logging
logger = logging.getLogger(__name__)
request_logger = logging.getLogger('django.request')
class Category(models.Model):
# Titel des Posts
title = models.CharField(max_length=200)
subtitle = models.CharField(max_length=500, null=True, blank=True)
# Slug = Text Basierter url bestandteil zb Fetsitzung 22.1.2020 --> fetsitzung_22_1_2020 für Url
slug = models.SlugField(unique=True, null=True, blank=True)
# Ein Haupt Bild für den Post
image = models.ImageField(null=True, blank=True)
tags = TaggableManager(blank=True)
class Meta:
verbose_name = "Category"
verbose_name_plural = "Categories"
class Post(models.Model):
# id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
legacy_id = models.IntegerField(null=True)
legacy_rubrik_id = models.IntegerField(null=True)
# Titel des Posts
title = models.CharField(verbose_name="Titel", max_length=200)
subtitle = models.CharField(max_length=500, null=True, blank=True)
# Slug = Text Basierter url bestandteil zb Fetsitzung 22.1.2020 --> fetsitzung_22_1_2020 für Url
slug = models.SlugField(unique=True, null=True, blank=True)
# Body Text Artikel Text soll später mit WYSIWG Editor bearbeitet werden
body = models.TextField(null=True, blank=True)
# Ein Haupt Bild für den Post
image = models.ImageField(null=True, blank=True)
# Wer hat das geschrieben
author = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, blank=True)
tags = TaggableManager(blank=True)
# Datum ab dem etwas öffentlich sein soll
public_date = models.DateField(verbose_name="Veröffentlichung", null=True, blank=True, default=timezone.now)
imported_from = models.CharField(max_length=200, null=True, blank=True)
__choices = [
('N', _('News')),
('E', _('Event')),
('F', _('FetMeeting'))
]
post_type = models.CharField(max_length=1, choices=__choices, editable=True)
# post is pinned at main page
is_pinned = models.BooleanField(verbose_name="ANGEHEFTET", default=False)
# post is hidden from newsfeed (e.g. about)
is_hidden = models.BooleanField(verbose_name="UNSICHTBAR", default=False)
# Zusatz Info wenn ein Event gepostet wird
event_start = models.DateTimeField(verbose_name="Event Start", null=True, blank=True)
event_end = models.DateTimeField(verbose_name="Event Ende", null=True, blank=True)
event_place = models.CharField(max_length=200, null=True, blank=True)
# Dokumente v.a. fuer Sitzungen
has_protocol = models.BooleanField(default=False)
has_agenda = models.BooleanField(default=False)
protocol_key = models.CharField(max_length=200, null=True, blank=True)
agenda_key = models.CharField(max_length=200, null=True, blank=True)
# TimeStamps
date_modified = models.DateTimeField(auto_now=True)
date_created = models.DateTimeField(auto_now_add=True)
# Managers
objects = PostManager()
articles = ArticleManager()
def get_tags(self):
"""Returns assigned tags as a comma seperated list."""
return ",".join(self.tags.names())
@property
def agenda_html(self):
if not self.agenda_key:
return None
html = getPadHTML(self.agenda_key)
return html
@agenda_html.setter
def agenda_html(self, value):
request_logger.info("Accessing etherpad ...")
if not self.agenda_key:
request_logger.info("not agenda key!")
if not value or value == "":
return value
self.agenda_key = self.get_agenda_key()
request_logger.info("AGENDA KEY: %s " % self.agenda_key)
request_logger.info("VALUE: %s " % value)
if self.agenda_key:
setPadHTML(self.agenda_key, value)
request_logger.info("set etherpad!")
return value
def get_agenda_key(self):
if not self.slug:
return None
try:
agenda_key = createPadifNotExists(self.slug + "-agenda")
except Exception as e:
raise ValidationError(
_('Die Agenda konnte nicht erstellt werden. Error: %(error)s'),
params={'error': str(e)},
)
return None
return agenda_key
def get_protocol_key(self):
if not self.slug:
return None
try:
protocol_key = createPadifNotExists(self.slug + "-protocol")
except Exception as e:
raise ValidationError(
_('Das Protokoll konnte nicht erstellt werden. Error: %(error)s'),
params={'error': str(e)},
)
return None
return protocol_key
@property
def get_tagnames(self):
return ["#%s" % t for t in self.tags.names()]
def imageurl(self):
""" returns the url to the image"""
if self.image:
return self.image.url
else:
image = self.find_an_image()
if image:
return image.url
else:
return ""
def key(self):
return self.slug or self.id
def find_an_image(self):
"find an image via another post"
# TODO: Explain why this image is selected on save of the image
# Query all posts that have a slug that equals one of the tags
posts1 = Post.objects.filter(
slug__in=self.tags.names()
).filter(image__isnull=False)[0:1].all()
if len(posts1) > 0:
return posts1.get().image
# posts2=self.tags.similar_objects()
# for p in posts2:
# if p.image is not None:
# return p.image
return None
@property
def url(self):
return reverse('posts.show', kwargs={"id": self.slug})
def save(self, *args, **kwargs):
# save the post with some defaults
if not self.public_date:
self.public_date = timezone.now().date()
if not self.slug:
self.slug = slugify(self.public_date) + "-" + slugify(self.title)
super().save(*args, **kwargs)
self.tags.set(
*re.findall(r'\#([\d\w-]+)', str(self.subtitle)),
*re.findall(r'\#([\d\w-]+)', str(self.title))
)
def __str__(self):
return "Post (%s, %s): %s " % (self.slug, self.public_date.strftime("%d.%m.%Y"), self.title)
class News(Post):
objects = NewsManager()
class Meta:
proxy = True
verbose_name = "News"
verbose_name_plural = "News"
def save(self, *args, **kwargs):
if not self.post_type:
self.post_type = 'N'
super().save(*args, **kwargs)
class Event(Post):
only_events = EventManager()
all_events = AllEventManager()
class Meta:
proxy = True
verbose_name = "Event"
verbose_name_plural = "Events"
def clean(self):
if self.event_end is None or self.event_start is None:
raise ValidationError(_('Das Datum des Events fehlt.'))
elif self.event_end < self.event_start:
raise ValidationError(_('Das Ende des Events liegt vor dem Beginn.'))
def save(self, *args, **kwargs):
if not self.post_type:
self.post_type = 'E'
super().save(*args, **kwargs)
class FetMeeting(Event):
objects = FetMeetingManager()
class Meta:
proxy = True
verbose_name = "Fet Sitzung"
verbose_name_plural = "Fet Sitzungen"
def __get_slug(self):
slug = slugify(self.event_start.date()) + "-" + slugify("Fachschaftssitzung")
if Post.objects.filter(slug=slug).exists():
if Post.objects.get(slug=slug).id != self.id:
raise ValidationError(
_('Es existiert bereits eine Sitzung mit demselben Datum.')
)
return None
return slug
def clean(self):
if self.event_start is None:
raise ValidationError(_('Das Datum des Events fehlt.'))
elif (self.event_end) and (self.event_end < self.event_start):
raise ValidationError(_('Das Ende des Events liegt vor dem Beginn.'))
if not self.slug:
self.slug = self.__get_slug()
if self.has_agenda:
self.agenda_key = self.get_agenda_key()
if self.has_protocol:
self.protocol_key = self.get_protocol_key()
def save(self, *args, **kwargs):
self.title = "Fachschaftssitzung"
# TODO
# self.image
if not self.post_type:
self.post_type = 'F'
if not self.event_place:
self.event_place = "FET"
# make duration 2 hours if not specified otherwise
if not self.event_end:
self.event_end = self.event_start + timedelta(hours=2)
super().save(*args, **kwargs)