Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

✨ support new placeholders ands static alias #4

Merged
merged 1 commit into from
Dec 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
42 changes: 28 additions & 14 deletions djangocms_export_page/export/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@
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, Page, Placeholder
from cms.models.fields import PlaceholderField

from djangocms_alias.models import Alias
from djangocms_page_meta.utils import get_page_meta

from djangocms_export_page import settings
Expand Down Expand Up @@ -101,9 +103,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 +130,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 +157,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 +266,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)
if isinstance(attribute, Placeholder):
placeholders.append(attribute)

components = [
Component(
Expand All @@ -273,8 +288,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
26 changes: 25 additions & 1 deletion djangocms_export_page/settings.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,36 @@
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 %}

28 changes: 27 additions & 1 deletion tests/factories.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import factory
from djangocms_alias.models import Alias, AliasContent, Category

from testapp.models import Blog

Expand All @@ -8,4 +9,29 @@ 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
24 changes: 22 additions & 2 deletions tests/test_models.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
from django.test import RequestFactory, TestCase
from django.test import RequestFactory, TestCase, override_settings

from cms.api import add_plugin

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

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


class ExportModelTests(TestCase):
Expand All @@ -12,6 +14,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 +27,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
Loading