nephila/djangocms-blog

View on GitHub
djangocms_blog/liveblog/models.py

Summary

Maintainability
A
0 mins
Test Coverage
from operator import itemgetter

from asgiref.sync import async_to_sync
from channels.layers import get_channel_layer
from cms.models import CMSPlugin
from cms.utils.plugins import reorder_plugins
from django.db import models
from django.template import Context
from django.utils.timezone import now
from django.utils.translation import gettext_lazy as _
from djangocms_text_ckeditor.models import AbstractText
from filer.fields.image import FilerImageField

from djangocms_blog.models import Post, thumbnail_model
from djangocms_blog.settings import DATE_FORMAT


class LiveblogInterface(models.Model):
    """
    Abstract Liveblog plugin model, reusable to customize the liveblogging
    plugins.

    When implementing this, you **must** call ``self._post_save()`` in the
    concrete plugin model ``save`` method.
    """

    publish = models.BooleanField(_("publish liveblog entry"), default=False)
    post_date = models.DateTimeField(_("post date"), blank=True, default=now)

    class Meta:
        verbose_name = _("liveblog entry")
        verbose_name_plural = _("liveblog entries")
        abstract = True

    def __str__(self):
        return str(self.pk)

    def _post_save(self):
        """
        Reorder plugins according to the post_date value. All (and only)
        subclasses of LiveblogInterface are taken into consideration and
        reordered together
        """
        items = []
        for model in LiveblogInterface.__subclasses__():
            items.extend(model.objects.filter(placeholder=self.placeholder).values("pk", "post_date"))
        order = reversed([item["pk"] for item in sorted(items, key=itemgetter("post_date"))])
        reorder_plugins(self.placeholder, None, self.language, order)

    @property
    def liveblog_group(self):
        post = Post.objects.language(self.language).filter(liveblog=self.placeholder).first()
        if post:
            return post.liveblog_group

    def render(self, request):
        context = Context({"request": request})
        from cms.plugin_rendering import ContentRenderer

        renderer = ContentRenderer(request)
        return renderer.render_plugin(
            instance=self,
            context=context,
            placeholder=self.placeholder,
        )

    def send(self, request):
        """
        Render the content and send to the related group
        """
        if self.liveblog_group:
            content = self.render(request)
            notification = {
                "id": self.pk,
                "content": content,
                "creation_date": self.post_date.strftime(DATE_FORMAT),
                "changed_date": self.changed_date.strftime(DATE_FORMAT),
                "type": "send.json",
            }
            channel_layer = get_channel_layer()
            group = self.liveblog_group
            async_to_sync(channel_layer.group_send)(group, notification)


class Liveblog(LiveblogInterface, AbstractText):
    """
    Basic liveblog plugin model
    """

    cmsplugin_ptr = models.OneToOneField(
        CMSPlugin, related_name="%(app_label)s_%(class)s", primary_key=True, parent_link=True, on_delete=models.CASCADE
    )
    title = models.CharField(_("title"), max_length=255)
    image = FilerImageField(
        verbose_name=_("image"),
        blank=True,
        null=True,
        on_delete=models.SET_NULL,
        related_name="djangocms_blog_liveblog_image",
    )
    thumbnail = models.ForeignKey(
        thumbnail_model,
        verbose_name=_("thumbnail size"),
        on_delete=models.SET_NULL,
        blank=True,
        null=True,
        related_name="djangocms_blog_liveblog_thumbnail",
    )

    class Meta:
        verbose_name = _("liveblog entry")
        verbose_name_plural = _("liveblog entries")

    def save(self, *args, **kwargs):
        super().save(*args, **kwargs)
        self._post_save()

    def __str__(self):
        return AbstractText.__str__(self)