Skip to content

Commit ca9c318

Browse files
feat: django-cms 5.0 compatibility & restored import callback invocation (#46)
1 parent 5a7e65a commit ca9c318

File tree

12 files changed

+83
-12
lines changed

12 files changed

+83
-12
lines changed

.github/workflows/test.yml

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,14 @@ jobs:
1010
matrix:
1111
python-version: [ "3.9", "3.10", "3.11", "3.12", "3.13"]
1212
requirements-file: [
13+
dj42_cms41.txt,
1314
dj50_cms41.txt,
1415
dj51_cms41.txt,
15-
dj42_cms41.txt,
16+
dj52_cms41.txt,
17+
dj42_cms50.txt,
18+
dj50_cms50.txt,
19+
dj51_cms50.txt,
20+
dj52_cms50.txt,
1621
]
1722
os: [
1823
ubuntu-latest,
@@ -22,6 +27,14 @@ jobs:
2227
python-version: 3.9
2328
- requirements-file: dj51_cms41.txt
2429
python-version: 3.9
30+
- requirements-file: dj52_cms41.txt
31+
python-version: 3.9
32+
- requirements-file: dj50_cms50.txt
33+
python-version: 3.9
34+
- requirements-file: dj51_cms50.txt
35+
python-version: 3.9
36+
- requirements-file: dj52_cms50.txt
37+
python-version: 3.9
2538
steps:
2639
- uses: actions/checkout@v4
2740
- name: Set up Python ${{ matrix.python-version }}

README.rst

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -91,14 +91,23 @@ different systems while setting the contents as you need it::
9191
})
9292
return plugin_data
9393

94-
def import_function(deserialized_object):
95-
some_related_object = MyModel.objects.first()
96-
for field in deserialized_object.object._meta.fields:
94+
def import_function(plugin, plugin_data):
95+
some_related_fallback_object = MyModel.objects.first()
96+
for field in plugin._meta.fields:
9797
# example of setting a default value for a related field
9898
if isinstance(field, ForeignKey):
99-
value = getattr(deserialized_object.object, field.attname)
100-
if field.related_model == MyModel and value is not None:
101-
setattr(deserialized_object.object, field.name, some_related_object)
99+
plugin_value = getattr(plugin, field.attname)
100+
raw_value = plugin_data[field.name]
101+
if (
102+
field.related_model == MyModel
103+
# related object is referenced, but does not exist
104+
and plugin_value is None and raw_value is not None
105+
):
106+
setattr(plugin, field.name, some_related_fallback_object)
107+
# There is no guarantee on whether djangocms-transfer saves the
108+
# plugin. It is recommended to do this yourself in case you changed
109+
# the plugin.
110+
plugin.save()
102111

103112

104113
Running Tests

djangocms_transfer/cms_plugins.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -160,11 +160,11 @@ def import_plugins_view(cls, request):
160160
request, obj=new_plugins[0]
161161
)
162162

163-
from cms.toolbar.utils import get_plugin_tree_as_json
163+
from cms.toolbar.utils import get_plugin_tree
164164

165165
# Placeholder plugins import
166166
new_plugins = placeholder.get_plugins(language).exclude(pk__in=tree_order)
167-
data = json.loads(get_plugin_tree_as_json(request, list(new_plugins)))
167+
data = get_plugin_tree(request, list(new_plugins))
168168
data["plugin_order"] = tree_order + ["__COPY__"]
169169
data["target_placeholder_id"] = placeholder.pk
170170
context = {"structure_data": json.dumps(data)}

djangocms_transfer/datastructures.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1+
import importlib
12
from collections import namedtuple
3+
from typing import Callable
24

35
from cms.api import add_plugin
46
from cms.models import CMSPlugin
@@ -66,6 +68,7 @@ def restore(self, placeholder, language, parent=None):
6668
target=parent,
6769
**data,
6870
)
71+
self._call_user_site_import_processor_if_necessary(plugin, self.data)
6972

7073
field = ("target",) if plugin_target else ()
7174
# An empty *update_fields* iterable will skip the save
@@ -91,3 +94,23 @@ def restore(self, placeholder, language, parent=None):
9194

9295
plugin.save()
9396
return plugin
97+
98+
def _call_user_site_import_processor_if_necessary(
99+
self, plugin: CMSPlugin, plugin_data: dict
100+
):
101+
# customize plugin-data on import with configured function
102+
if processor_symbol := getattr(
103+
settings, "DJANGOCMS_TRANSFER_PROCESS_IMPORT_PLUGIN_DATA", None
104+
):
105+
function = self._resolve_function_from_full_path(processor_symbol)
106+
function(plugin, plugin_data)
107+
108+
def _resolve_function_from_full_path(
109+
self, fully_qualified_path: str
110+
) -> Callable:
111+
try:
112+
module_name, function_name = fully_qualified_path.rsplit(".", 1)
113+
module = importlib.import_module(module_name)
114+
return getattr(module, function_name)
115+
except (AttributeError, ImportError):
116+
raise ImportError(f"could not resolve {fully_qualified_path}")

djangocms_transfer/forms.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,10 @@ def run_export(self):
133133

134134

135135
class PluginImportForm(ExportImportForm):
136-
import_file = forms.FileField(required=True)
136+
import_file = forms.FileField(
137+
required=True,
138+
widget=forms.FileInput(attrs={"accept": "application/json"}),
139+
)
137140

138141
def clean(self):
139142
if self.errors:

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ classifiers = [
3636
"Framework :: Django :: 5.1",
3737
"Framework :: Django CMS",
3838
"Framework :: Django CMS :: 4.1",
39+
"Framework :: Django CMS :: 5.0",
3940
"Topic :: Internet :: WWW/HTTP",
4041
"Topic :: Internet :: WWW/HTTP :: Dynamic Content",
4142
"Topic :: Software Development",

tests/requirements/dj42_cms50.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
-r base.txt
2+
3+
Django>=4.2,<5.0
4+
django-cms>=5.0,<5.1

tests/requirements/dj50_cms50.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
-r base.txt
2+
3+
Django>=5.0,<5.1
4+
django-cms>=5.0,<5.1

tests/requirements/dj51_cms50.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
-r base.txt
2+
3+
Django>=5.1,<5.2
4+
django-cms>=5.0,<5.1

tests/requirements/dj52_cms41.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
-r base.txt
2+
3+
Django>=5.2,<5.3
4+
django-cms>=4.1,<4.2

0 commit comments

Comments
 (0)