Skip to content

Commit

Permalink
✨ support new placeholders ands static alias
Browse files Browse the repository at this point in the history
  • Loading branch information
Coperh committed Dec 16, 2024
1 parent 3dd033b commit f9f35af
Show file tree
Hide file tree
Showing 11 changed files with 178 additions and 32 deletions.
14 changes: 7 additions & 7 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -116,16 +116,16 @@ add the following to the model class:
It's better to put the PlaceholderField (here `content`) in a separate section.


Static Placeholders
Static Aliases
-------------------

If you also want to export the static placeholders of a page, some extra configuration
is required. There is a setting called `EXPORT_STATIC_PLACEHOLDERS`.
If you also want to export the static aliases of a page, some extra configuration
is required. There is a setting called `EXPORT_STATIC_ALIASES`.

.. code-block:: python
EXPORT_STATIC_PLACEHOLDERS = {
'template_name': ['static_placeholder_code']
EXPORT_STATIC_ALIASES = {
'template_name': ['static_alias_code']
}
So with the cms settings it will look like this:
Expand All @@ -134,15 +134,15 @@ So with the cms settings it will look like this:
# test.html
<div>
{% static_placeholder 'test-placeholder' %}
{% static_alias 'test-placeholder' %}
</div>
# settings.py
CMS_TEMPLATES = [
('test.html', _('Test page')),
]
EXPORT_STATIC_PLACEHOLDERS = {
EXPORT_STATIC_ALIASES = {
'test.html': ['test-placeholder']
}
Expand Down
43 changes: 29 additions & 14 deletions djangocms_export_page/export/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,15 @@
from django.contrib.sites.shortcuts import get_current_site
from django.db.models import CharField, ForeignKey, TextField

from cms.models import CMSPlugin, Placeholder, StaticPlaceholder
from cms.models import CMSPlugin, Placeholder, StaticPlaceholder, Page
from cms.models.fields import PlaceholderField
from djangocms_page_meta.utils import get_page_meta

from djangocms_export_page import settings

from djangocms_alias.models import Alias


from ..utils import clean_value

Section = namedtuple("Section", ["name", "section", "components"])
Expand Down Expand Up @@ -101,9 +104,14 @@ def get_base_url(self):
)

def get_page_url(self):
return "{domain}{url}".format(
domain=self.get_base_url(), url=self.object.get_absolute_url(self.language)
)

# requires language to get teh URL
if isinstance(self.object, Page):
url = self.object.get_absolute_url(self.language)
else:
url = self.object.get_absolute_url()

return "{domain}{url}".format(domain=self.get_base_url(), url=url)

def export(self):
raise NotImplementedError
Expand All @@ -123,9 +131,9 @@ def get_data(self):
plugins = self.get_ordered_plugins(placeholder, self.language)
for plugin in plugins:
components.extend(self.get_components(plugin))
elif isinstance(section, StaticPlaceholder):
placeholder = section
plugins = self.get_ordered_plugins(placeholder.public, self.language)
elif isinstance(section, Alias):
placeholder = section.get_placeholder(self.language)
plugins = self.get_ordered_plugins(placeholder, self.language)
for plugin in plugins:
components.extend(self.get_components(plugin))

Expand All @@ -150,9 +158,9 @@ def get_sections(self):
)
)
if hasattr(self.object, "template"):
codes = settings.EXPORT_STATIC_PLACEHOLDERS.get(self.object.template)
codes = settings.EXPORT_STATIC_ALIASES.get(self.object.template)
if codes:
queryset = StaticPlaceholder.objects.filter(code__in=codes)
queryset = Alias.objects.filter(static_code__in=codes)
sections.extend(self.get_static_placeholders(queryset))

if self.page_meta:
Expand Down Expand Up @@ -259,11 +267,19 @@ def get_defined_components(self, obj, field_names=None):
in the placeholder fields.
"""
field_names = field_names if field_names else obj._export_page["fields"]

model_fields = {f.name: f for f in obj._meta.fields}
fields = [(name, model_fields[name]) for name in field_names]

regular_fields = [f for f in fields if not isinstance(f[1], PlaceholderField)]
placeholder_fields = [f for f in fields if isinstance(f[1], PlaceholderField)]
regular_fields = []
placeholders = []

for field_name in field_names:
if field_name in model_fields:
regular_fields.append((field_name, model_fields[field_name]))
elif hasattr(obj, field_name):
attribute = getattr(obj, field_name)
print("Here", attribute)
placeholders.append(attribute)

components = [
Component(
Expand All @@ -273,8 +289,7 @@ def get_defined_components(self, obj, field_names=None):
)
]

for field_name, field in placeholder_fields:
placeholder = getattr(obj, field_name)
for placeholder in placeholders:
plugins = self.get_ordered_plugins(placeholder, self.language)
for plugin in plugins:
components.extend(self.get_components(plugin))
Expand Down
27 changes: 26 additions & 1 deletion djangocms_export_page/settings.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,37 @@
import sys

from warnings import warn


from django.conf import settings


class _Settings(object):

_placeholder_dep_msg = (
"Static Placeholders are disabled form Django CMS 4. Pleas use djangocms-alias's static_alias "
"and use the EXPORT_STATIC_ALIASES setting"
)

@property
def EXPORT_STATIC_PLACEHOLDERS(self):
return getattr(settings, "EXPORT_STATIC_PLACEHOLDERS", {})

warn(self._placeholder_dep_msg, DeprecationWarning, stacklevel=2)

setting = getattr(settings, "EXPORT_STATIC_PLACEHOLDERS", {})
return setting

@property
def EXPORT_STATIC_ALIASES(self):

old_setting = getattr(settings, "EXPORT_STATIC_PLACEHOLDERS", {})

if old_setting:
warn(self._placeholder_dep_msg, DeprecationWarning, stacklevel=2)

return old_setting

return getattr(settings, "EXPORT_STATIC_ALIASES", {})

def __getattr__(self, name):
return globals()[name]
Expand Down
6 changes: 4 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ requires-python = ">=3.10"
dependencies = [
"django~=3.2.0",
"django-cms>=4.1",
"djangocms-page-meta@git+https://github.com/maykinmedia/djangocms-page-meta@77f464d93bcc4cb525814632b92a82738da5ef8e",
"djangocms-alias",
"djangocms-page-meta-maykin",
"python-docx",
]

Expand Down Expand Up @@ -65,8 +66,9 @@ profile = "black"
combine_as_imports = true
skip = ["env", ".tox", ".history", ".eggs"]
known_django = "django"
known_cms = "cms"
known_first_party="djangocms_export_page"
sections=["FUTURE", "STDLIB", "DJANGO", "THIRDPARTY", "FIRSTPARTY", "LOCALFOLDER"]
sections=["FUTURE", "STDLIB", "DJANGO", "CMS", "THIRDPARTY", "FIRSTPARTY", "LOCALFOLDER"]

[tool.pytest.ini_options]
testpaths = ["tests"]
Expand Down
25 changes: 23 additions & 2 deletions testapp/models.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,37 @@
from django.db import models
from django.urls import NoReverseMatch, reverse

from django.utils.functional import cached_property
from cms.models.fields import PlaceholderRelationField
from cms.utils.placeholder import get_placeholder_from_slot

from autoslug import AutoSlugField


# Create your models here.
class Blog(models.Model):

_export_page = {
"sections": [
{"name": "Meta", "fields": ["title", "slug", "date_posted"]},
{"name": "Body", "fields": ["content"]},
],
}

title = models.CharField(max_length=100)
content = models.TextField()
slug = AutoSlugField(populate_from="title", editable=True, blank=True)
date_posted = models.DateTimeField(auto_now_add=True)

placeholders = PlaceholderRelationField()

@cached_property
def content(self):
return get_placeholder_from_slot(self.placeholders, "blog_content")

def __str__(self):
return self.title

def get_absolute_url(self, *args, **kwargs):
def get_absolute_url(self):
try:
return reverse(
"blog:detail",
Expand All @@ -28,3 +45,7 @@ def get_absolute_url(self, *args, **kwargs):

def get_title(self):
return self.title

@property
def template(self):
return "blog.html"
1 change: 1 addition & 0 deletions testapp/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
"easy_thumbnails",
"djangocms_text_ckeditor",
"meta",
"djangocms_alias",
"djangocms_page_meta",
"djangocms_export_page",
"testapp",
Expand Down
12 changes: 12 additions & 0 deletions testapp/templates/blog.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@

{% load cms_tags djangocms_alias_tags %}


{% block content %}

{% render_placeholder 'instance.blog_content' %}


{% static_alias 'footer' %}
{% endblock content %}

4 changes: 3 additions & 1 deletion testapp/templates/test.html
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@

{% load cms_tags %}
{% load cms_tags djangocms_alias_tags %}


{% block content %}

{% placeholder 'test' %}

{% static_alias 'footer' %}

{% endblock content %}

29 changes: 28 additions & 1 deletion tests/factories.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,37 @@

from testapp.models import Blog

from djangocms_alias.models import Alias, Category, AliasContent


class BlogFactory(factory.django.DjangoModelFactory):
class Meta:
model = Blog

title = factory.Faker("sentence", nb_words=4)
content = factory.Faker("text")


class CategoryFactory(factory.django.DjangoModelFactory):
class Meta:
model = Category


class AliasContentFactory(factory.django.DjangoModelFactory):

class Meta:
model = AliasContent


class AliasFactory(factory.django.DjangoModelFactory):

category = factory.SubFactory(CategoryFactory)

static_code = factory.Faker("word")

log = factory.RelatedFactory(
AliasContentFactory,
factory_related_name="alias",
)

class Meta:
model = Alias
23 changes: 21 additions & 2 deletions tests/test_models.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
from django.test import RequestFactory, TestCase
from cms.api import add_plugin
from django.test import RequestFactory, TestCase, override_settings

from djangocms_export_page.export.common import PageExport
from djangocms_export_page.export.docx import DocxPageExport

from .factories import BlogFactory
from .factories import BlogFactory, AliasFactory


class ExportModelTests(TestCase):
Expand All @@ -12,6 +13,9 @@ def setUp(self):
self.language = "nl"
self.request = RequestFactory().get(self.object.get_absolute_url())

static_alias = AliasFactory(static_code="footer")
self.static_placeholder = static_alias.get_placeholder(self.language)

def test_model_export(self):
export = DocxPageExport(self.request, self.object, language=self.language)
export_file = export.export()
Expand All @@ -22,3 +26,18 @@ def test_page_url(self):
self.assertEqual(
export.page_url, "http://example.com" + self.object.get_absolute_url()
)

@override_settings(EXPORT_STATIC_ALIASES={"blog.html": ["footer"]})
def test_page_with_placeholders(self):
add_plugin(
self.object.content, "TextPlugin", self.language, body="Body Content"
)

add_plugin(
self.static_placeholder, "TextPlugin", self.language, body="footer info"
)
export = DocxPageExport(self.request, self.object, language=self.language)

data = export.get_data()
self.assertEqual(data[1].components[1].fields[0].value, "Body Content")
self.assertEqual(data[2].components[0].fields[0].value, "footer info")
Loading

0 comments on commit f9f35af

Please sign in to comment.