Source code for pagetools.widgets.models
from django import template
from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation
from django.contrib.contenttypes.models import ContentType
from django.core.exceptions import ValidationError
from django.db import models
from django.utils.html import format_html
from django.utils.safestring import mark_safe
from django.utils.translation import gettext_lazy as _
from pagetools.models import LangManager, LangModel
from pagetools.utils import get_adminedit_url, import_cls
from . import settings
[docs]class BaseWidget(models.Model):
template_name = "widgets/basewidget.html"
title = models.CharField(max_length=128, blank=True)
name = models.SlugField(_("name"), unique=True)
adapter = GenericRelation("widgets.WidgetInArea")
[docs] def get_template_name(self, context): # pylint: disable=unused-argument
return self.template_name
[docs] def render(self, context, request):
templ = template.loader.get_template(self.get_template_name(context))
context["title"] = self.get_title(context)
context["content"] = self.get_content(context, request)
return mark_safe(templ.render(context, request=request))
[docs] def get_content(self, context, request): # pylint: disable=unused-argument
raise NotImplementedError()
def __str__(self):
return "%s:%s" % (self.name, self.title)
[docs]class ContentWidget(BaseWidget):
"""
A wiget with a text area
"""
content = models.TextField(_("Content"))
[docs] def get_content(self, context, request): # pylint: disable=unused-argument
return self.content
class Meta:
verbose_name = _("Simple Text Widget")
verbose_name_plural = _("Simple Text Widgets")
[docs]class TemplateTagWidget(BaseWidget):
"""
Renders a TemplateTag
"""
key_choices = [(key, key) for key in sorted(settings.TEMPLATETAG_WIDGETS.keys())]
renderclasskey = models.CharField(max_length=255, choices=key_choices)
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.templatetag_instance = None
[docs] def load_templatetag_instance(self):
"""Set the TemplateTag-like instance"""
if not self.templatetag_instance:
clzname = settings.TEMPLATETAG_WIDGETS.get(self.renderclasskey, (None))
clz = import_cls(clzname)
if clz:
self.templatetag_instance = clz()
return self.templatetag_instance
[docs] def get_content(self, context, request):
if self.load_templatetag_instance():
context["request"] = request
return self.templatetag_instance.render(context)
return None
[docs]class PageType(models.Model):
"""A key that defines which additional context should be added to the context."""
name = models.CharField("Name", max_length=128)
parent = models.ForeignKey("self", blank=True, null=True, on_delete=models.CASCADE)
def __str__(self):
return self.name
class Meta:
verbose_name = _("Pagetype")
verbose_name_plural = _("Pagetypes")
[docs]class TypeArea(LangModel):
"""An area associated with a `PageType`"""
area = models.CharField(max_length=64, choices=sorted(settings.AREAS))
pagetype = models.ForeignKey(PageType, on_delete=models.CASCADE)
objects = LangManager()
[docs] def clean(self):
super().clean()
filtered = TypeArea.objects.filter(area=self.area, pagetype=self.pagetype, lang="").exclude(pk=self.pk)
if filtered:
raise ValidationError({"__all__": ("Language Error",)})
def __str__(self):
return "%s_%s%s" % (
self.area,
self.pagetype,
("_%s" % self.lang if self.lang else ""),
)
class Meta:
unique_together = ("area", "pagetype", "lang")
verbose_name = _("Pagetype-Area")
verbose_name_plural = _("Pagetype-Areas")
[docs]class WidgetInArea(models.Model):
"""A widget associated with an area"""
typearea = models.ForeignKey(TypeArea, related_name="widgets", on_delete=models.CASCADE)
content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
object_id = models.PositiveIntegerField()
content_object = GenericForeignKey("content_type", "object_id")
position = models.PositiveIntegerField()
enabled = models.BooleanField("enabled", default=False)
[docs] def get_content(self, contextdict, request):
return self.content_object.render(contextdict, request)
[docs] def adminedit_url(self):
obj = self.content_object
return format_html('<a href="{0}">{1}</a>', get_adminedit_url(obj), obj)
def __str__(self):
return "%s@%s" % (self.content_object, self.typearea.pagetype)
class Meta:
ordering = ["position"]
verbose_name = _("Included widget")
verbose_name_plural = _("Included widgets")