From 986abd10ea961afbd63fbf84772d1aa6b38dd888 Mon Sep 17 00:00:00 2001 From: Matt Westcott Date: Thu, 26 Apr 2018 19:26:10 +0100 Subject: [PATCH] Implement get_model / get_instance on link/embed handlers --- wagtail/core/rich_text/__init__.py | 39 +++++++++++++++++++++++++ wagtail/core/rich_text/pages.py | 15 ++++++++-- wagtail/documents/rich_text/__init__.py | 15 ++++++---- wagtail/embeds/rich_text/__init__.py | 13 ++++++++- wagtail/images/rich_text/__init__.py | 16 ++++++---- 5 files changed, 84 insertions(+), 14 deletions(-) diff --git a/wagtail/core/rich_text/__init__.py b/wagtail/core/rich_text/__init__.py index 4b9c63b17..2066ff2d0 100644 --- a/wagtail/core/rich_text/__init__.py +++ b/wagtail/core/rich_text/__init__.py @@ -1,3 +1,4 @@ +from django.db.models import Model from django.utils.safestring import mark_safe from wagtail.core.rich_text.feature_registry import FeatureRegistry @@ -50,3 +51,41 @@ class RichText: def __bool__(self): return bool(self.source) __nonzero__ = __bool__ + + +class EntityHandler: + """ + An 'entity' is a placeholder tag within the saved rich text, which needs to be rewritten + into real HTML at the point of rendering. Typically (but not necessarily) the entity will + be a reference to a model to be fetched to have its data output into the rich text content + (so that we aren't storing potentially changeable data within the saved rich text). + + An EntityHandler defines how this rewriting is performed. + + Currently Wagtail supports two kinds of entity: links (represented as ...) + and embeds (represented as ). + """ + @staticmethod + def get_model(): + return NotImplementedError + + @classmethod + def get_instance(cls, attrs: dict) -> Model: + model = cls.get_model() + return model._default_manager.get(id=attrs['id']) + + @staticmethod + def expand_db_attributes(attrs: dict) -> str: + """ + Given a dict of attributes from the entity tag + stored in the database, returns the real HTML representation. + """ + raise NotImplementedError + + +class LinkHandler(EntityHandler): + pass + + +class EmbedHandler(EntityHandler): + pass diff --git a/wagtail/core/rich_text/pages.py b/wagtail/core/rich_text/pages.py index 9cf331463..d5f8bbdfb 100644 --- a/wagtail/core/rich_text/pages.py +++ b/wagtail/core/rich_text/pages.py @@ -1,13 +1,22 @@ from django.utils.html import escape from wagtail.core.models import Page +from wagtail.core.rich_text import LinkHandler -class PageLinkHandler: +class PageLinkHandler(LinkHandler): @staticmethod - def expand_db_attributes(attrs): + def get_model(): + return Page + + @classmethod + def get_instance(cls, attrs): + return super().get_instance(attrs).specific + + @classmethod + def expand_db_attributes(cls, attrs): try: - page = Page.objects.get(id=attrs['id']) + page = cls.get_instance(attrs) return '' % escape(page.specific.url) except Page.DoesNotExist: return "" diff --git a/wagtail/documents/rich_text/__init__.py b/wagtail/documents/rich_text/__init__.py index 876fb6093..f0a307e51 100644 --- a/wagtail/documents/rich_text/__init__.py +++ b/wagtail/documents/rich_text/__init__.py @@ -1,16 +1,21 @@ +from django.core.exceptions import ObjectDoesNotExist from django.utils.html import escape +from wagtail.core.rich_text import LinkHandler from wagtail.documents.models import get_document_model # Front-end conversion -class DocumentLinkHandler: +class DocumentLinkHandler(LinkHandler): @staticmethod - def expand_db_attributes(attrs): - Document = get_document_model() + def get_model(): + return get_document_model() + + @classmethod + def expand_db_attributes(cls, attrs): try: - doc = Document.objects.get(id=attrs['id']) + doc = cls.get_instance(attrs) return '' % escape(doc.url) - except (Document.DoesNotExist, KeyError): + except (ObjectDoesNotExist, KeyError): return "" diff --git a/wagtail/embeds/rich_text/__init__.py b/wagtail/embeds/rich_text/__init__.py index 5a8c2c729..b852c16a4 100644 --- a/wagtail/embeds/rich_text/__init__.py +++ b/wagtail/embeds/rich_text/__init__.py @@ -1,9 +1,20 @@ +from wagtail.core.rich_text import EmbedHandler from wagtail.embeds import format +from wagtail.embeds.embeds import get_embed +from wagtail.embeds.models import Embed # Front-end conversion -class MediaEmbedHandler: +class MediaEmbedHandler(EmbedHandler): + @staticmethod + def get_model(): + return Embed + + @staticmethod + def get_instance(attrs): + return get_embed(attrs['url']) + @staticmethod def expand_db_attributes(attrs): """ diff --git a/wagtail/images/rich_text/__init__.py b/wagtail/images/rich_text/__init__.py index f6a2a938c..429c439dc 100644 --- a/wagtail/images/rich_text/__init__.py +++ b/wagtail/images/rich_text/__init__.py @@ -1,20 +1,26 @@ +from django.core.exceptions import ObjectDoesNotExist + +from wagtail.core.rich_text import EmbedHandler from wagtail.images import get_image_model from wagtail.images.formats import get_image_format # Front-end conversion -class ImageEmbedHandler: +class ImageEmbedHandler(EmbedHandler): @staticmethod - def expand_db_attributes(attrs): + def get_model(): + return get_image_model() + + @classmethod + def expand_db_attributes(cls, attrs): """ Given a dict of attributes from the tag, return the real HTML representation for use on the front-end. """ - Image = get_image_model() try: - image = Image.objects.get(id=attrs['id']) - except Image.DoesNotExist: + image = cls.get_instance(attrs) + except ObjectDoesNotExist: return "" image_format = get_image_format(attrs['format'])