djangocms-render-context 1.0.0__py3-none-any.whl → 1.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- djangocms_render_context/__init__.py +1 -1
- djangocms_render_context/cms_plugins.py +1 -0
- djangocms_render_context/forms.py +22 -3
- djangocms_render_context/loaders.py +21 -1
- djangocms_render_context/locale/cs/LC_MESSAGES/django.mo +0 -0
- djangocms_render_context/locale/cs/LC_MESSAGES/django.po +11 -5
- djangocms_render_context/migrations/0001_initial.py +0 -2
- djangocms_render_context/migrations/0002_rendercontext_mimetype.py +33 -0
- djangocms_render_context/models.py +10 -6
- {djangocms_render_context-1.0.0.dist-info → djangocms_render_context-1.1.0.dist-info}/METADATA +2 -1
- djangocms_render_context-1.1.0.dist-info/RECORD +17 -0
- djangocms_render_context/encoders.py +0 -8
- djangocms_render_context-1.0.0.dist-info/RECORD +0 -17
- {djangocms_render_context-1.0.0.dist-info → djangocms_render_context-1.1.0.dist-info}/WHEEL +0 -0
- {djangocms_render_context-1.0.0.dist-info → djangocms_render_context-1.1.0.dist-info}/top_level.txt +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = "1.
|
|
1
|
+
__version__ = "1.1.0"
|
|
@@ -11,10 +11,18 @@ from django.template.exceptions import TemplateSyntaxError
|
|
|
11
11
|
from django.template.loader import get_template
|
|
12
12
|
from django.utils.translation import gettext_lazy as _
|
|
13
13
|
from filer.models.filemodels import File
|
|
14
|
+
from sekizai.context import SekizaiContext
|
|
14
15
|
|
|
15
16
|
from .cache import get_cache_key
|
|
16
17
|
from .exceptions import SourceParseFailure
|
|
17
|
-
from .loaders import
|
|
18
|
+
from .loaders import (
|
|
19
|
+
CONTEXT_DATA_FORMATS,
|
|
20
|
+
LOADERS,
|
|
21
|
+
SUPPORTED_FILE_TYPES,
|
|
22
|
+
get_data_from_file,
|
|
23
|
+
get_data_from_url,
|
|
24
|
+
value_to_bytes,
|
|
25
|
+
)
|
|
18
26
|
|
|
19
27
|
TEMPLATES = (("", ""),)
|
|
20
28
|
|
|
@@ -24,6 +32,11 @@ sourceType = Union[str, File] # noqa: UP007
|
|
|
24
32
|
class RenderContextForm(ModelForm):
|
|
25
33
|
"""Render Context Form."""
|
|
26
34
|
|
|
35
|
+
mimetype = forms.ChoiceField(
|
|
36
|
+
label=_("Type of Data for context"),
|
|
37
|
+
choices=CONTEXT_DATA_FORMATS,
|
|
38
|
+
help_text=_("The format must be consistent with the data in the context."),
|
|
39
|
+
)
|
|
27
40
|
template_list = forms.ChoiceField(
|
|
28
41
|
label=_("Template list"),
|
|
29
42
|
required=False,
|
|
@@ -51,10 +64,16 @@ class RenderContextForm(ModelForm):
|
|
|
51
64
|
except SourceParseFailure as error:
|
|
52
65
|
self.add_error(name, error)
|
|
53
66
|
|
|
67
|
+
def check_context_data(self, value: str, mimetype: str) -> Context:
|
|
68
|
+
try:
|
|
69
|
+
return Context(LOADERS[mimetype](value_to_bytes(value, mimetype)))
|
|
70
|
+
except SourceParseFailure as error:
|
|
71
|
+
self.add_error("context", error)
|
|
72
|
+
|
|
54
73
|
def check_context(self, cleaned_data: dict) -> Context:
|
|
55
74
|
context = Context({})
|
|
56
75
|
if cleaned_data["context"]:
|
|
57
|
-
context =
|
|
76
|
+
context = self.check_context_data(cleaned_data["context"], cleaned_data["mimetype"])
|
|
58
77
|
elif cleaned_data["file"]:
|
|
59
78
|
context = self.check_value("file", cleaned_data["file"], get_data_from_file)
|
|
60
79
|
elif cleaned_data["source"]:
|
|
@@ -78,7 +97,7 @@ class RenderContextForm(ModelForm):
|
|
|
78
97
|
template = get_template(cleaned_data["template_list"]).template
|
|
79
98
|
if template:
|
|
80
99
|
try:
|
|
81
|
-
template.render(context)
|
|
100
|
+
template.render(SekizaiContext(context))
|
|
82
101
|
except (TemplateDoesNotExist, TemplateSyntaxError) as error:
|
|
83
102
|
self.add_error(field_name, error)
|
|
84
103
|
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import base64
|
|
2
|
+
import binascii
|
|
1
3
|
import csv
|
|
2
4
|
import json
|
|
3
5
|
import xml.etree.ElementTree as ET
|
|
@@ -47,6 +49,17 @@ def get_data_from_file(source: File) -> dataType:
|
|
|
47
49
|
return LOADERS[source.mime_type](source.file.read())
|
|
48
50
|
|
|
49
51
|
|
|
52
|
+
def value_to_bytes(value: str, mimetype: str) -> bytes:
|
|
53
|
+
if mimetype == "application/vnd.oasis.opendocument.spreadsheet":
|
|
54
|
+
try:
|
|
55
|
+
content = base64.b64decode(value)
|
|
56
|
+
except (binascii.Error, ValueError) as err:
|
|
57
|
+
raise SourceParseFailure(err) from err
|
|
58
|
+
else:
|
|
59
|
+
content = value.encode("utf8")
|
|
60
|
+
return content
|
|
61
|
+
|
|
62
|
+
|
|
50
63
|
def load_json(content: bytes) -> dataType:
|
|
51
64
|
try:
|
|
52
65
|
return json.load(BytesIO(content))
|
|
@@ -90,7 +103,7 @@ def load_spreadsheet(content: bytes) -> dataType:
|
|
|
90
103
|
try:
|
|
91
104
|
handle = zipfile.ZipFile(BytesIO(content))
|
|
92
105
|
payload = handle.read("content.xml")
|
|
93
|
-
except (zipfile.BadZipFile, KeyError) as err:
|
|
106
|
+
except (zipfile.BadZipFile, KeyError, ValueError) as err:
|
|
94
107
|
raise SourceParseFailure(err) from err
|
|
95
108
|
finally:
|
|
96
109
|
if handle is None:
|
|
@@ -212,3 +225,10 @@ LOADERS = {
|
|
|
212
225
|
"application/xml": load_xml,
|
|
213
226
|
"application/vnd.oasis.opendocument.spreadsheet": load_spreadsheet,
|
|
214
227
|
}
|
|
228
|
+
CONTEXT_DATA_FORMATS = (
|
|
229
|
+
("application/json", "JSON"),
|
|
230
|
+
("application/yaml", "YAML"),
|
|
231
|
+
("application/xml", "XML"),
|
|
232
|
+
("text/csv", "CSV"),
|
|
233
|
+
("application/vnd.oasis.opendocument.spreadsheet", "ODS (in Base64)"),
|
|
234
|
+
)
|
|
Binary file
|
|
@@ -7,7 +7,7 @@ msgid ""
|
|
|
7
7
|
msgstr ""
|
|
8
8
|
"Project-Id-Version: PACKAGE VERSION\n"
|
|
9
9
|
"Report-Msgid-Bugs-To: \n"
|
|
10
|
-
"POT-Creation-Date:
|
|
10
|
+
"POT-Creation-Date: 2026-01-09 09:26+0100\n"
|
|
11
11
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
|
12
12
|
"Last-Translator: Zdeněk Böhm <zdenek.bohm@nic.cz>\n"
|
|
13
13
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
|
@@ -25,11 +25,11 @@ msgstr ""
|
|
|
25
25
|
"zdrojový soubor nepoužije i přesto, že je zadán."
|
|
26
26
|
|
|
27
27
|
msgid ""
|
|
28
|
-
"Context data in
|
|
29
|
-
"source URL."
|
|
28
|
+
"Context data in selected format. They take precedence over the source file "
|
|
29
|
+
"and source URL."
|
|
30
30
|
msgstr ""
|
|
31
|
-
"Data pro kontext
|
|
32
|
-
"URL zdroje."
|
|
31
|
+
"Data pro kontext v nastaveném formátu. Mají přednost před zdrojovým souborem "
|
|
32
|
+
"a URL zdroje."
|
|
33
33
|
|
|
34
34
|
msgid "Data for context"
|
|
35
35
|
msgstr "Data pro kontext"
|
|
@@ -94,6 +94,9 @@ msgstr ""
|
|
|
94
94
|
"kontext nebo Zdrojový soubor, tak se URL zdroje nepoužije i přesto, že je "
|
|
95
95
|
"zadáno."
|
|
96
96
|
|
|
97
|
+
msgid "The format must be consistent with the data in the context."
|
|
98
|
+
msgstr "Formát musí odpovídat datům v kontextu."
|
|
99
|
+
|
|
97
100
|
msgid ""
|
|
98
101
|
"The time in minutes during which data will not be retrieved from the Source "
|
|
99
102
|
"URL, but will remain in the cache. If set to zero, data from the source URL "
|
|
@@ -103,5 +106,8 @@ msgstr ""
|
|
|
103
106
|
"zůstanou ponechána v cache. Je-li nastavena nula, tak se data z URL zdroje "
|
|
104
107
|
"do cache neukládají, ale načítají se pokaždé."
|
|
105
108
|
|
|
109
|
+
msgid "Type of Data for context"
|
|
110
|
+
msgstr "Typ dat pro kontext"
|
|
111
|
+
|
|
106
112
|
msgid "Unsupported file mime type: "
|
|
107
113
|
msgstr "Nepodporovaný mime typ souboru: "
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
# Generated by Django 5.2.8 on 2025-12-10 09:02
|
|
2
2
|
|
|
3
3
|
import django.db.models.deletion
|
|
4
|
-
import djangocms_render_context.encoders
|
|
5
4
|
import filer.fields.file
|
|
6
5
|
from django.db import migrations, models
|
|
7
6
|
|
|
@@ -35,7 +34,6 @@ class Migration(migrations.Migration):
|
|
|
35
34
|
"context",
|
|
36
35
|
models.JSONField(
|
|
37
36
|
blank=True,
|
|
38
|
-
encoder=djangocms_render_context.encoders.PrettyJsonEncoder,
|
|
39
37
|
help_text="Context data in JSON format. They take precedence over the source file and source URL.",
|
|
40
38
|
null=True,
|
|
41
39
|
verbose_name="Data for context",
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# Generated by Django 5.2.9 on 2026-01-09 07:40
|
|
2
|
+
|
|
3
|
+
from django.db import migrations, models
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class Migration(migrations.Migration):
|
|
7
|
+
|
|
8
|
+
dependencies = [
|
|
9
|
+
("djangocms_render_context", "0001_initial"),
|
|
10
|
+
]
|
|
11
|
+
|
|
12
|
+
operations = [
|
|
13
|
+
migrations.AddField(
|
|
14
|
+
model_name="rendercontext",
|
|
15
|
+
name="mimetype",
|
|
16
|
+
field=models.CharField(
|
|
17
|
+
default="application/json",
|
|
18
|
+
help_text="The format must be consistent with the data in the context.",
|
|
19
|
+
max_length=255,
|
|
20
|
+
verbose_name="Type of Data for context",
|
|
21
|
+
),
|
|
22
|
+
),
|
|
23
|
+
migrations.AlterField(
|
|
24
|
+
model_name="rendercontext",
|
|
25
|
+
name="context",
|
|
26
|
+
field=models.TextField(
|
|
27
|
+
blank=True,
|
|
28
|
+
help_text="Context data in selected format. They take precedence over the source file and source URL.",
|
|
29
|
+
null=True,
|
|
30
|
+
verbose_name="Data for context",
|
|
31
|
+
),
|
|
32
|
+
),
|
|
33
|
+
]
|
|
@@ -5,20 +5,24 @@ from django.db import models
|
|
|
5
5
|
from django.utils.translation import gettext_lazy as _
|
|
6
6
|
from filer.fields.file import FilerFileField
|
|
7
7
|
|
|
8
|
-
from .encoders import PrettyJsonEncoder
|
|
9
8
|
from .exceptions import SourceParseFailure
|
|
10
|
-
from .loaders import get_cached_data_from_url, get_data_from_file
|
|
9
|
+
from .loaders import LOADERS, get_cached_data_from_url, get_data_from_file, value_to_bytes
|
|
11
10
|
|
|
12
11
|
LOGGER = logging.getLogger(__name__)
|
|
13
12
|
|
|
14
13
|
|
|
15
14
|
class RenderContext(CMSPlugin):
|
|
16
|
-
|
|
15
|
+
mimetype = models.CharField(
|
|
16
|
+
verbose_name=_("Type of Data for context"),
|
|
17
|
+
max_length=255,
|
|
18
|
+
default="application/json",
|
|
19
|
+
help_text=_("The format must be consistent with the data in the context."),
|
|
20
|
+
)
|
|
21
|
+
context = models.TextField(
|
|
17
22
|
verbose_name=_("Data for context"),
|
|
18
23
|
null=True,
|
|
19
24
|
blank=True,
|
|
20
|
-
|
|
21
|
-
help_text=_("Context data in JSON format. They take precedence over the source file and source URL."),
|
|
25
|
+
help_text=_("Context data in selected format. They take precedence over the source file and source URL."),
|
|
22
26
|
)
|
|
23
27
|
file = FilerFileField(
|
|
24
28
|
verbose_name=_("Source file"),
|
|
@@ -82,7 +86,7 @@ class RenderContext(CMSPlugin):
|
|
|
82
86
|
|
|
83
87
|
def get_data(self):
|
|
84
88
|
if self.context:
|
|
85
|
-
return self.context
|
|
89
|
+
return LOADERS[self.mimetype](value_to_bytes(self.context, self.mimetype))
|
|
86
90
|
elif self.file:
|
|
87
91
|
try:
|
|
88
92
|
return get_data_from_file(self.file)
|
{djangocms_render_context-1.0.0.dist-info → djangocms_render_context-1.1.0.dist-info}/METADATA
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: djangocms-render-context
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.1.0
|
|
4
4
|
Summary: Render context into template.
|
|
5
5
|
Author-email: Zdeněk Böhm <zdenek.bohm@nic.cz>
|
|
6
6
|
License-Expression: BSD-3-Clause
|
|
@@ -26,6 +26,7 @@ Requires-Python: >=3.9
|
|
|
26
26
|
Description-Content-Type: text/markdown
|
|
27
27
|
Requires-Dist: django-cms<6,>=4.0
|
|
28
28
|
Requires-Dist: django-filer~=3.4
|
|
29
|
+
Requires-Dist: django-sekizai~=4.1
|
|
29
30
|
Requires-Dist: pyyaml
|
|
30
31
|
Requires-Dist: requests
|
|
31
32
|
Provides-Extra: quality
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
djangocms_render_context/__init__.py,sha256=LGVQyDsWifdACo7qztwb8RWWHds1E7uQ-ZqD8SAjyw4,22
|
|
2
|
+
djangocms_render_context/cache.py,sha256=PwagqDTqh3I83e7Ru52ei4P05juZ6Ob_pILukGGtsTo,99
|
|
3
|
+
djangocms_render_context/cms_plugins.py,sha256=GMtqfSyn2YM48ifgJSTJ5LyRBA0WhvIkqtF_ymMBwME,1623
|
|
4
|
+
djangocms_render_context/exceptions.py,sha256=r5L-U90T_60CPSagcwWmu_r6DkbHAghg04uS8OvzTPo,69
|
|
5
|
+
djangocms_render_context/forms.py,sha256=3gmFDTcqwXp9FNfZvIHbuSWsTzdkBuidcnGsQlX9B2o,4392
|
|
6
|
+
djangocms_render_context/loaders.py,sha256=s3uRG-SBhZ_vlBf01dGc3usGiyVHTrA_vvDmw80zgdQ,7400
|
|
7
|
+
djangocms_render_context/models.py,sha256=OqWONL6LaEeEBOgcjOk1QpeEE4qeip-FHUbdHrNWlkQ,3648
|
|
8
|
+
djangocms_render_context/utils.py,sha256=HmkARbCxCJ6-SNRuH7zI4BY3BBf87c9cQuwBUNId53I,1632
|
|
9
|
+
djangocms_render_context/locale/cs/LC_MESSAGES/django.mo,sha256=ML6jtfvv6ZzClweXXeqJmHRvWzH-iUkJozA40OkYyZ8,3126
|
|
10
|
+
djangocms_render_context/locale/cs/LC_MESSAGES/django.po,sha256=kn-ZDENpLYDwaooBdM50qM_oCRfjXpMb2Eo7H8Jg3Kk,3352
|
|
11
|
+
djangocms_render_context/migrations/0001_initial.py,sha256=tg3Wu_KMfykrQKn2kYMm_3COyheNA6mqWv3h-IxnXqk,3728
|
|
12
|
+
djangocms_render_context/migrations/0002_rendercontext_mimetype.py,sha256=6FHuX_5U4lHWbH37145wuPSvdPqqEgVIbdPGEXec1ck,1006
|
|
13
|
+
djangocms_render_context/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
14
|
+
djangocms_render_context-1.1.0.dist-info/METADATA,sha256=eCo5vGsqPH6I2BymyT8c2IEEa1qyZ5XbwX5f3Xc_bYk,2900
|
|
15
|
+
djangocms_render_context-1.1.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
16
|
+
djangocms_render_context-1.1.0.dist-info/top_level.txt,sha256=J82yBJeJTHoDzwzFIU3i4jFHxn3nAjgn-Fn5JSjVKQ8,25
|
|
17
|
+
djangocms_render_context-1.1.0.dist-info/RECORD,,
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
djangocms_render_context/__init__.py,sha256=J-j-u0itpEFT6irdmWmixQqYMadNl1X91TxUmoiLHMI,22
|
|
2
|
-
djangocms_render_context/cache.py,sha256=PwagqDTqh3I83e7Ru52ei4P05juZ6Ob_pILukGGtsTo,99
|
|
3
|
-
djangocms_render_context/cms_plugins.py,sha256=YBNH5Rh79xdC2puO3HOLZ0R6miUDBelGd-rmPAQ2Epo,1591
|
|
4
|
-
djangocms_render_context/encoders.py,sha256=TIIcj_6vgXlUH5D0oeozCA7ixN4WNnfrnk15bAmfpQ8,253
|
|
5
|
-
djangocms_render_context/exceptions.py,sha256=r5L-U90T_60CPSagcwWmu_r6DkbHAghg04uS8OvzTPo,69
|
|
6
|
-
djangocms_render_context/forms.py,sha256=bpfoWoHUZXzhobH_fekH5txXRLQIKjMsxl8n6Yi-6fs,3754
|
|
7
|
-
djangocms_render_context/loaders.py,sha256=JUFOwXCPbRG-4J79nrIT1AiRgq_je7km5VGhnO22Uxs,6774
|
|
8
|
-
djangocms_render_context/models.py,sha256=BmdQQi47vZjkf1vaQr7KyfeSw9tAmY0atnoNfA2AgxI,3404
|
|
9
|
-
djangocms_render_context/utils.py,sha256=HmkARbCxCJ6-SNRuH7zI4BY3BBf87c9cQuwBUNId53I,1632
|
|
10
|
-
djangocms_render_context/locale/cs/LC_MESSAGES/django.mo,sha256=sxF9h5d4-av6CQoVXCSIKuIw_KMyCzmKJ7N74rD0hus,2903
|
|
11
|
-
djangocms_render_context/locale/cs/LC_MESSAGES/django.po,sha256=bQMJnXI6CkCbMfbJ56SvirX1_rJOVwFLxJjFe2tsQeE,3157
|
|
12
|
-
djangocms_render_context/migrations/0001_initial.py,sha256=bdIs0Jl8M8JcC-i03vxp612Lim_mUJ-BOaq2D3YI6uw,3854
|
|
13
|
-
djangocms_render_context/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
14
|
-
djangocms_render_context-1.0.0.dist-info/METADATA,sha256=k1wb9eo0N7fBlLk8Xm4nv5zWddbQSJRjrcsQxYwEmSA,2865
|
|
15
|
-
djangocms_render_context-1.0.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
16
|
-
djangocms_render_context-1.0.0.dist-info/top_level.txt,sha256=J82yBJeJTHoDzwzFIU3i4jFHxn3nAjgn-Fn5JSjVKQ8,25
|
|
17
|
-
djangocms_render_context-1.0.0.dist-info/RECORD,,
|
|
File without changes
|
{djangocms_render_context-1.0.0.dist-info → djangocms_render_context-1.1.0.dist-info}/top_level.txt
RENAMED
|
File without changes
|