Skip to content

Commit

Permalink
fix: Delay importing models.CMSPlugin in utils. (#637)
Browse files Browse the repository at this point in the history
  • Loading branch information
mbi authored Nov 30, 2022
1 parent 9ac4c15 commit c8d5fce
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 20 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ Changelog
Unreleased
==========

* Fix `468 <https://github.com/django-cms/djangocms-text-ckeditor/issues/468>`_ via `637 <https://github.com/django-cms/djangocms-text-ckeditor/pull/637>`_: Delay importing models.CMSPlugin in utils to allow adding an HTMLField to a custom user model.


5.1.1 (2022-06-22)
==================

Expand Down
52 changes: 32 additions & 20 deletions djangocms_text_ckeditor/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,19 @@
from django.template.loader import render_to_string
from django.utils.functional import LazyObject

from cms.models import CMSPlugin

from classytags.utils import flatten_context


OBJ_ADMIN_RE_PATTERN = r'<cms-plugin .*?\bid="(?P<pk>\d+)".*?>.*?</cms-plugin>'
OBJ_ADMIN_WITH_CONTENT_RE_PATTERN = r'<cms-plugin .*?\bid="(?P<pk>\d+)".*?>(?P<content>.*?)</cms-plugin>'
OBJ_ADMIN_WITH_CONTENT_RE_PATTERN = (
r'<cms-plugin .*?\bid="(?P<pk>\d+)".*?>(?P<content>.*?)</cms-plugin>'
)
OBJ_ADMIN_RE = re.compile(OBJ_ADMIN_RE_PATTERN, flags=re.DOTALL)


def _render_cms_plugin(plugin, context):
context = flatten_context(context)
context['plugin'] = plugin
context["plugin"] = plugin

# This my fellow ckeditor enthusiasts is a hack..

Expand All @@ -34,9 +34,9 @@ def _render_cms_plugin(plugin, context):
# and thus calls context processors AND render the plugin manually with the context
# after it's been bound to a template.
response = render_to_string(
'cms/plugins/render_plugin_preview.html',
"cms/plugins/render_plugin_preview.html",
context,
request=context['request'],
request=context["request"],
)
return response

Expand All @@ -49,10 +49,11 @@ def wrapped_view(*args, **kwargs):
response = view_func(*args, **kwargs)
response._random_comment_exempt = True
return response

return wraps(view_func, assigned=WRAPPER_ASSIGNMENTS)(wrapped_view)


def plugin_to_tag(obj, content='', admin=False):
def plugin_to_tag(obj, content="", admin=False):
plugin_attrs = OrderedDict(
id=obj.pk,
icon_alt=force_escape(obj.get_instance_icon_alt()),
Expand All @@ -62,12 +63,12 @@ def plugin_to_tag(obj, content='', admin=False):
if admin:
# Include extra attributes when rendering on the admin
plugin_class = obj.get_plugin_class()
preview = getattr(plugin_class, 'text_editor_preview', True)
preview = getattr(plugin_class, "text_editor_preview", True)
plugin_tag = (
'<cms-plugin render-plugin=%(preview)s alt="%(icon_alt)s "'
'title="%(icon_alt)s" id="%(id)d">%(content)s</cms-plugin>'
)
plugin_attrs['preview'] = 'true' if preview else 'false'
plugin_attrs["preview"] = "true" if preview else "false"
else:
plugin_tag = (
'<cms-plugin alt="%(icon_alt)s "'
Expand All @@ -79,10 +80,11 @@ def plugin_to_tag(obj, content='', admin=False):
def plugin_tags_to_id_list(text, regex=OBJ_ADMIN_RE):
def _find_plugins():
for tag in regex.finditer(text):
plugin_id = tag.groupdict().get('pk')
plugin_id = tag.groupdict().get("pk")

if plugin_id:
yield plugin_id

return [int(_id) for _id in _find_plugins()]


Expand All @@ -96,59 +98,67 @@ def _plugin_tags_to_html(text, output_func):

def _render_tag(m):
try:
plugin_id = int(m.groupdict()['pk'])
plugin_id = int(m.groupdict()["pk"])
obj = plugins_by_id[plugin_id]
except KeyError:
# Object must have been deleted. It cannot be rendered to
# end user so just remove it from the HTML altogether
return ''
return ""
else:
obj._render_meta.text_enabled = True
return output_func(obj, m)

return OBJ_ADMIN_RE.sub(_render_tag, text)


def plugin_tags_to_user_html(text, context):
def _render_plugin(obj, match):
return _render_cms_plugin(obj, context)

return _plugin_tags_to_html(text, output_func=_render_plugin)


def plugin_tags_to_admin_html(text, context):
def _render_plugin(obj, match):
plugin_content = _render_cms_plugin(obj, context)
return plugin_to_tag(obj, content=plugin_content, admin=True)

return _plugin_tags_to_html(text, output_func=_render_plugin)


def plugin_tags_to_db(text):
def _strip_plugin_content(obj, match):
return plugin_to_tag(obj).strip()

return _plugin_tags_to_html(text, output_func=_strip_plugin_content)


def replace_plugin_tags(text, id_dict, regex=OBJ_ADMIN_RE):
from cms.models import CMSPlugin

plugins_by_id = CMSPlugin.objects.in_bulk(id_dict.values())

def _replace_tag(m):
try:
plugin_id = int(m.groupdict()['pk'])
plugin_id = int(m.groupdict()["pk"])
new_id = id_dict[plugin_id]
plugin = plugins_by_id[new_id]
except KeyError:
# Object must have been deleted. It cannot be rendered to
# end user, or edited, so just remove it from the HTML
# altogether
return ''
return ""
return plugin_to_tag(plugin)

return regex.sub(_replace_tag, text)


def get_plugins_from_text(text, regex=OBJ_ADMIN_RE):
from cms.models import CMSPlugin
from cms.utils.plugins import downcast_plugins

plugin_ids = plugin_tags_to_id_list(text, regex)
plugins = CMSPlugin.objects.filter(pk__in=plugin_ids).select_related('placeholder')
plugins = CMSPlugin.objects.filter(pk__in=plugin_ids).select_related("placeholder")
plugin_list = downcast_plugins(plugins, select_placeholder=True)
return {plugin.pk: plugin for plugin in plugin_list}

Expand All @@ -157,14 +167,16 @@ def get_plugins_from_text(text, regex=OBJ_ADMIN_RE):
The following class is taken from https://github.com/jezdez/django/compare/feature/staticfiles-templatetag
and should be removed and replaced by the django-core version in 1.4
"""
default_storage = 'django.contrib.staticfiles.storage.StaticFilesStorage'
default_storage = "django.contrib.staticfiles.storage.StaticFilesStorage"


class ConfiguredStorage(LazyObject):

def _setup(self):
from django.conf import settings
self._wrapped = get_storage_class(getattr(settings, 'STATICFILES_STORAGE', default_storage))()

self._wrapped = get_storage_class(
getattr(settings, "STATICFILES_STORAGE", default_storage)
)()


configured_storage = ConfiguredStorage()
Expand All @@ -175,5 +187,5 @@ def static_url(path):
Helper that prefixes a URL with STATIC_URL and cms
"""
if not path:
return ''
return configured_storage.url(os.path.join('', path))
return ""
return configured_storage.url(os.path.join("", path))

0 comments on commit c8d5fce

Please sign in to comment.