django-cms-qe 3.2.0__py3-none-any.whl → 3.3.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.
@@ -26,6 +26,7 @@ INSTALLED_APPS = [
26
26
  'cms_qe_table',
27
27
  'cms_qe_video',
28
28
  'cms_qe_analytical',
29
+ 'cms_qe_plugins',
29
30
 
30
31
  # Must be before django.contrib.admin.
31
32
  'djangocms_admin_style',
@@ -0,0 +1,50 @@
1
+ CROSS_ORIGINS = (
2
+ 'anonymous',
3
+ 'use-credentials',
4
+ )
5
+
6
+ LOADING = (
7
+ 'eager',
8
+ 'lazy',
9
+ )
10
+
11
+ SANDBOX = (
12
+ 'allow-forms',
13
+ 'allow-pointer-lock',
14
+ 'allow-popups',
15
+ 'allow-same-origin',
16
+ 'allow-scripts',
17
+ 'allow-top-navigation',
18
+ )
19
+
20
+ REFERRER_POLICY = (
21
+ 'no-referrer',
22
+ 'no-referrer-when-downgrade',
23
+ 'origin',
24
+ 'origin-when-cross-origin',
25
+ 'unsafe-url',
26
+ )
27
+
28
+ SCRIPT_REFERRER_POLICY = REFERRER_POLICY + (
29
+ 'same-origin',
30
+ 'strict-origin',
31
+ 'strict-origin-when-cross-origin',
32
+ )
33
+
34
+ REL = (
35
+ 'alternate',
36
+ 'author',
37
+ 'dns-prefetch',
38
+ 'help',
39
+ 'icon',
40
+ 'license',
41
+ 'next',
42
+ 'pingback',
43
+ 'preconnect',
44
+ 'prefetch',
45
+ 'preload',
46
+ 'prerender',
47
+ 'prev',
48
+ 'search',
49
+ 'stylesheet',
50
+ )
@@ -0,0 +1,31 @@
1
+ from cms.plugin_base import CMSPluginBase
2
+ from cms.plugin_pool import plugin_pool
3
+
4
+ from .models import Iframe, Link, Script
5
+
6
+
7
+ @plugin_pool.register_plugin
8
+ class LinkTagPlugin(CMSPluginBase):
9
+
10
+ model = Link
11
+ name = 'LINK'
12
+ module = 'HTML Elements'
13
+ render_template = "cms_qe_plugins/link.html"
14
+
15
+
16
+ @plugin_pool.register_plugin
17
+ class ScriptTagPlugin(CMSPluginBase):
18
+
19
+ model = Script
20
+ name = 'SCRIPT'
21
+ module = 'HTML Elements'
22
+ render_template = "cms_qe_plugins/script.html"
23
+
24
+
25
+ @plugin_pool.register_plugin
26
+ class IframeTagPlugin(CMSPluginBase):
27
+
28
+ model = Iframe
29
+ name = 'IFRAME'
30
+ module = 'HTML Elements'
31
+ render_template = "cms_qe_plugins/iframe.html"
@@ -0,0 +1,433 @@
1
+ # Generated by Django 4.2.13 on 2024-06-04 08:08
2
+
3
+ import cms_qe_plugins.validators
4
+ import django.core.serializers.json
5
+ from django.db import migrations, models
6
+ import django.db.models.deletion
7
+
8
+
9
+ class Migration(migrations.Migration):
10
+
11
+ initial = True
12
+
13
+ dependencies = []
14
+
15
+ operations = [
16
+ migrations.CreateModel(
17
+ name="Iframe",
18
+ fields=[
19
+ (
20
+ "cmsplugin_ptr",
21
+ models.OneToOneField(
22
+ auto_created=True,
23
+ on_delete=django.db.models.deletion.CASCADE,
24
+ parent_link=True,
25
+ primary_key=True,
26
+ related_name="%(app_label)s_%(class)s",
27
+ serialize=False,
28
+ to="cms.cmsplugin",
29
+ ),
30
+ ),
31
+ (
32
+ "src",
33
+ models.CharField(
34
+ help_text="Specifies the address of the document to embed in the <iframe>.",
35
+ max_length=255,
36
+ validators=[cms_qe_plugins.validators.validate_url_or_path],
37
+ ),
38
+ ),
39
+ (
40
+ "allow",
41
+ models.CharField(
42
+ blank=True,
43
+ help_text="Specifies a feature policy for the &lt;iframe&gt;. Form more see <a href='https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe#allow' target='_blank'>IFrame attributes.</a>.",
44
+ max_length=255,
45
+ null=True,
46
+ ),
47
+ ),
48
+ (
49
+ "allow_full_screen",
50
+ models.BooleanField(
51
+ blank=True,
52
+ help_text="Set to true if the &lt;iframe&gt; can activate fullscreen mode by calling the requestFullscreen() method.",
53
+ null=True,
54
+ ),
55
+ ),
56
+ (
57
+ "allow_payment_request",
58
+ models.BooleanField(
59
+ blank=True,
60
+ help_text="Set to true if a cross-origin &lt;iframe&gt; should be allowed to invoke the Payment Request API.",
61
+ null=True,
62
+ ),
63
+ ),
64
+ (
65
+ "height",
66
+ models.IntegerField(
67
+ blank=True,
68
+ help_text="Specifies the height of an &lt;iframe&gt;. Default height is 150 pixels.",
69
+ null=True,
70
+ ),
71
+ ),
72
+ (
73
+ "width",
74
+ models.IntegerField(
75
+ blank=True,
76
+ help_text="Specifies the width of an &lt;iframe&gt;. Default width is 300 pixels.",
77
+ null=True,
78
+ ),
79
+ ),
80
+ (
81
+ "loading",
82
+ models.CharField(
83
+ blank=True,
84
+ choices=[("", ""), ("eager", "eager"), ("lazy", "lazy")],
85
+ default=None,
86
+ help_text="Specifies whether a browser should load an iframe immediately or to defer loading of iframes until some conditions are met.",
87
+ max_length=255,
88
+ null=True,
89
+ ),
90
+ ),
91
+ (
92
+ "name",
93
+ models.CharField(
94
+ blank=True,
95
+ help_text="Specifies the name of an &lt;iframe&gt;.",
96
+ max_length=255,
97
+ null=True,
98
+ ),
99
+ ),
100
+ (
101
+ "referrer_policy",
102
+ models.CharField(
103
+ blank=True,
104
+ choices=[
105
+ ("", ""),
106
+ ("no-referrer", "no-referrer"),
107
+ (
108
+ "no-referrer-when-downgrade",
109
+ "no-referrer-when-downgrade",
110
+ ),
111
+ ("origin", "origin"),
112
+ ("origin-when-cross-origin", "origin-when-cross-origin"),
113
+ ("unsafe-url", "unsafe-url"),
114
+ ("same-origin", "same-origin"),
115
+ ("strict-origin", "strict-origin"),
116
+ (
117
+ "strict-origin-when-cross-origin",
118
+ "strict-origin-when-cross-origin",
119
+ ),
120
+ ],
121
+ default=None,
122
+ help_text="Specifies which referrer information to send when fetching the iframe.",
123
+ max_length=50,
124
+ null=True,
125
+ ),
126
+ ),
127
+ (
128
+ "sandbox",
129
+ models.CharField(
130
+ blank=True,
131
+ choices=[
132
+ ("", ""),
133
+ ("allow-forms", "allow-forms"),
134
+ ("allow-pointer-lock", "allow-pointer-lock"),
135
+ ("allow-popups", "allow-popups"),
136
+ ("allow-same-origin", "allow-same-origin"),
137
+ ("allow-scripts", "allow-scripts"),
138
+ ("allow-top-navigation", "allow-top-navigation"),
139
+ ],
140
+ default=None,
141
+ help_text="Enables an extra set of restrictions for the content in an &lt;iframe&gt;.",
142
+ max_length=50,
143
+ null=True,
144
+ ),
145
+ ),
146
+ (
147
+ "src_doc",
148
+ models.TextField(
149
+ blank=True,
150
+ help_text="Specifies the HTML content of the page to show in the &lt;iframe&gt;.",
151
+ null=True,
152
+ ),
153
+ ),
154
+ (
155
+ "attributes",
156
+ models.JSONField(
157
+ blank=True,
158
+ encoder=django.core.serializers.json.DjangoJSONEncoder,
159
+ help_text='More attributes as JSON data. E.g. {"data-name": "value", "id": 42}',
160
+ null=True,
161
+ ),
162
+ ),
163
+ ],
164
+ options={
165
+ "abstract": False,
166
+ },
167
+ bases=("cms.cmsplugin",),
168
+ ),
169
+ migrations.CreateModel(
170
+ name="Link",
171
+ fields=[
172
+ (
173
+ "cmsplugin_ptr",
174
+ models.OneToOneField(
175
+ auto_created=True,
176
+ on_delete=django.db.models.deletion.CASCADE,
177
+ parent_link=True,
178
+ primary_key=True,
179
+ related_name="%(app_label)s_%(class)s",
180
+ serialize=False,
181
+ to="cms.cmsplugin",
182
+ ),
183
+ ),
184
+ (
185
+ "href",
186
+ models.CharField(
187
+ help_text="Specifies the location of the linked document.",
188
+ max_length=255,
189
+ validators=[cms_qe_plugins.validators.validate_url_or_path],
190
+ ),
191
+ ),
192
+ (
193
+ "rel",
194
+ models.CharField(
195
+ choices=[
196
+ ("alternate", "alternate"),
197
+ ("author", "author"),
198
+ ("dns-prefetch", "dns-prefetch"),
199
+ ("help", "help"),
200
+ ("icon", "icon"),
201
+ ("license", "license"),
202
+ ("next", "next"),
203
+ ("pingback", "pingback"),
204
+ ("preconnect", "preconnect"),
205
+ ("prefetch", "prefetch"),
206
+ ("preload", "preload"),
207
+ ("prerender", "prerender"),
208
+ ("prev", "prev"),
209
+ ("search", "search"),
210
+ ("stylesheet", "stylesheet"),
211
+ ],
212
+ default="stylesheet",
213
+ help_text="Required. Specifies the relationship between the current document and the linked document.",
214
+ max_length=30,
215
+ ),
216
+ ),
217
+ (
218
+ "cross_origin",
219
+ models.CharField(
220
+ blank=True,
221
+ choices=[
222
+ ("", ""),
223
+ ("anonymous", "anonymous"),
224
+ ("use-credentials", "use-credentials"),
225
+ ],
226
+ default=None,
227
+ help_text="Specifies how the element handles cross-origin requests.",
228
+ max_length=15,
229
+ null=True,
230
+ ),
231
+ ),
232
+ (
233
+ "hreflang",
234
+ models.CharField(
235
+ blank=True,
236
+ help_text="Specifies the language of the text in the linked document.",
237
+ max_length=30,
238
+ null=True,
239
+ ),
240
+ ),
241
+ (
242
+ "media",
243
+ models.CharField(
244
+ blank=True,
245
+ help_text="Specifies on what device the linked document will be displayed.",
246
+ max_length=255,
247
+ null=True,
248
+ ),
249
+ ),
250
+ (
251
+ "referrer_policy",
252
+ models.CharField(
253
+ blank=True,
254
+ choices=[
255
+ ("", ""),
256
+ ("no-referrer", "no-referrer"),
257
+ (
258
+ "no-referrer-when-downgrade",
259
+ "no-referrer-when-downgrade",
260
+ ),
261
+ ("origin", "origin"),
262
+ ("origin-when-cross-origin", "origin-when-cross-origin"),
263
+ ("unsafe-url", "unsafe-url"),
264
+ ],
265
+ default=None,
266
+ help_text="Specifies which referrer to use when fetching the resource.",
267
+ max_length=50,
268
+ null=True,
269
+ ),
270
+ ),
271
+ (
272
+ "sizes",
273
+ models.CharField(
274
+ blank=True,
275
+ help_text='Specifies the size of the linked resource. Only for rel="icon".',
276
+ max_length=255,
277
+ null=True,
278
+ ),
279
+ ),
280
+ (
281
+ "title",
282
+ models.CharField(
283
+ blank=True,
284
+ help_text="Defines a preferred or an alternate stylesheet.",
285
+ max_length=255,
286
+ null=True,
287
+ ),
288
+ ),
289
+ (
290
+ "type",
291
+ models.CharField(
292
+ blank=True,
293
+ help_text="Specifies the media type of the linked document. E.g. 'text/css'.",
294
+ max_length=255,
295
+ null=True,
296
+ ),
297
+ ),
298
+ (
299
+ "attributes",
300
+ models.JSONField(
301
+ blank=True,
302
+ encoder=django.core.serializers.json.DjangoJSONEncoder,
303
+ help_text='More attributes as JSON data. E.g. {"data-name": "value", "id": 42}',
304
+ null=True,
305
+ ),
306
+ ),
307
+ ],
308
+ options={
309
+ "abstract": False,
310
+ },
311
+ bases=("cms.cmsplugin",),
312
+ ),
313
+ migrations.CreateModel(
314
+ name="Script",
315
+ fields=[
316
+ (
317
+ "cmsplugin_ptr",
318
+ models.OneToOneField(
319
+ auto_created=True,
320
+ on_delete=django.db.models.deletion.CASCADE,
321
+ parent_link=True,
322
+ primary_key=True,
323
+ related_name="%(app_label)s_%(class)s",
324
+ serialize=False,
325
+ to="cms.cmsplugin",
326
+ ),
327
+ ),
328
+ (
329
+ "src",
330
+ models.CharField(
331
+ help_text="Specifies the location of the linked script.",
332
+ max_length=255,
333
+ validators=[cms_qe_plugins.validators.validate_url_or_path],
334
+ ),
335
+ ),
336
+ (
337
+ "asyncf",
338
+ models.BooleanField(
339
+ default=False,
340
+ help_text="Specifies that the script is downloaded in parallel to parsing the page, and executed as soon as it is available (before parsing completes) (only for external scripts)",
341
+ verbose_name="async",
342
+ ),
343
+ ),
344
+ (
345
+ "cross_origin",
346
+ models.CharField(
347
+ blank=True,
348
+ choices=[
349
+ ("", ""),
350
+ ("anonymous", "anonymous"),
351
+ ("use-credentials", "use-credentials"),
352
+ ],
353
+ default=None,
354
+ help_text="Sets the mode of the request to an HTTP CORS Request.",
355
+ max_length=15,
356
+ null=True,
357
+ ),
358
+ ),
359
+ (
360
+ "defer",
361
+ models.BooleanField(
362
+ default=False,
363
+ help_text="Specifies that the script is downloaded in parallel to parsing the page, and executed after the page has finished parsing (only for external scripts)",
364
+ ),
365
+ ),
366
+ (
367
+ "integrity",
368
+ models.CharField(
369
+ blank=True,
370
+ help_text="Allows a browser to check the fetched script to ensure that the code is never loaded if the source has been manipulated",
371
+ max_length=255,
372
+ null=True,
373
+ ),
374
+ ),
375
+ (
376
+ "nomodule",
377
+ models.BooleanField(
378
+ default=False,
379
+ help_text="Specifies that the script should not be executed in browsers supporting ES2015 modules.",
380
+ ),
381
+ ),
382
+ (
383
+ "referrer_policy",
384
+ models.CharField(
385
+ blank=True,
386
+ choices=[
387
+ ("", ""),
388
+ ("no-referrer", "no-referrer"),
389
+ (
390
+ "no-referrer-when-downgrade",
391
+ "no-referrer-when-downgrade",
392
+ ),
393
+ ("origin", "origin"),
394
+ ("origin-when-cross-origin", "origin-when-cross-origin"),
395
+ ("unsafe-url", "unsafe-url"),
396
+ ("same-origin", "same-origin"),
397
+ ("strict-origin", "strict-origin"),
398
+ (
399
+ "strict-origin-when-cross-origin",
400
+ "strict-origin-when-cross-origin",
401
+ ),
402
+ ],
403
+ default=None,
404
+ help_text="Specifies which referrer to use when fetching the resource.",
405
+ max_length=50,
406
+ null=True,
407
+ ),
408
+ ),
409
+ (
410
+ "type",
411
+ models.CharField(
412
+ blank=True,
413
+ help_text="Specifies the media type of the script.",
414
+ max_length=255,
415
+ null=True,
416
+ ),
417
+ ),
418
+ (
419
+ "attributes",
420
+ models.JSONField(
421
+ blank=True,
422
+ encoder=django.core.serializers.json.DjangoJSONEncoder,
423
+ help_text='More attributes as JSON data. E.g. {"data-name": "value", "id": 42}',
424
+ null=True,
425
+ ),
426
+ ),
427
+ ],
428
+ options={
429
+ "abstract": False,
430
+ },
431
+ bases=("cms.cmsplugin",),
432
+ ),
433
+ ]
File without changes
@@ -0,0 +1,137 @@
1
+ from cms.models.pluginmodel import CMSPlugin
2
+ from django.core.serializers.json import DjangoJSONEncoder
3
+ from django.db import models
4
+
5
+ from .attributes import CROSS_ORIGINS, LOADING, REFERRER_POLICY, REL, SANDBOX, SCRIPT_REFERRER_POLICY
6
+ from .utils import make_choices, make_opt_choices
7
+ from .validators import validate_url_or_path
8
+
9
+
10
+ class Script(CMSPlugin):
11
+ """HTML Script tag."""
12
+
13
+ src = models.CharField(
14
+ max_length=255, validators=[validate_url_or_path],
15
+ help_text="Specifies the location of the linked script.")
16
+ asyncf = models.BooleanField(
17
+ default=False,
18
+ verbose_name='async',
19
+ help_text='Specifies that the script is downloaded in parallel to parsing the page, and executed as soon as it '
20
+ 'is available (before parsing completes) (only for external scripts)'
21
+ )
22
+ cross_origin = models.CharField(
23
+ max_length=15, null=True, blank=True, choices=make_opt_choices(CROSS_ORIGINS), default=None,
24
+ help_text="Sets the mode of the request to an HTTP CORS Request.")
25
+ defer = models.BooleanField(
26
+ default=False,
27
+ help_text='Specifies that the script is downloaded in parallel to parsing the page, and executed after '
28
+ 'the page has finished parsing (only for external scripts)'
29
+ )
30
+ integrity = models.CharField(
31
+ max_length=255, null=True, blank=True,
32
+ help_text='Allows a browser to check the fetched script to ensure that the code is never loaded '
33
+ 'if the source has been manipulated'
34
+ )
35
+ nomodule = models.BooleanField(
36
+ default=False,
37
+ help_text='Specifies that the script should not be executed in browsers supporting ES2015 modules.'
38
+ )
39
+ referrer_policy = models.CharField(
40
+ max_length=50, null=True, blank=True, choices=make_opt_choices(SCRIPT_REFERRER_POLICY), default=None,
41
+ help_text="Specifies which referrer to use when fetching the resource.")
42
+ type = models.CharField(
43
+ max_length=255, null=True, blank=True,
44
+ help_text="Specifies the media type of the script.")
45
+ attributes = models.JSONField(
46
+ null=True, blank=True, encoder=DjangoJSONEncoder,
47
+ help_text='More attributes as JSON data. E.g. {"data-name": "value", "id": 42}')
48
+
49
+ def __str__(self):
50
+ return self.src
51
+
52
+
53
+ class Link(CMSPlugin):
54
+ """HTML Link tag."""
55
+
56
+ href = models.CharField(
57
+ max_length=255, validators=[validate_url_or_path],
58
+ help_text="Specifies the location of the linked document.")
59
+ rel = models.CharField(
60
+ max_length=30, choices=make_choices(REL), default='stylesheet',
61
+ help_text="Required. Specifies the relationship between the current document and the linked document.")
62
+ cross_origin = models.CharField(
63
+ max_length=15, null=True, blank=True, choices=make_opt_choices(CROSS_ORIGINS), default=None,
64
+ help_text="Specifies how the element handles cross-origin requests.")
65
+ hreflang = models.CharField(
66
+ max_length=30, null=True, blank=True, help_text="Specifies the language of the text in the linked document.")
67
+ media = models.CharField(
68
+ max_length=255, null=True, blank=True,
69
+ help_text="Specifies on what device the linked document will be displayed.")
70
+ referrer_policy = models.CharField(
71
+ max_length=50, null=True, blank=True, choices=make_opt_choices(REFERRER_POLICY), default=None,
72
+ help_text="Specifies which referrer to use when fetching the resource.")
73
+ sizes = models.CharField(
74
+ max_length=255, null=True, blank=True,
75
+ help_text='Specifies the size of the linked resource. Only for rel="icon".')
76
+ title = models.CharField(
77
+ max_length=255, null=True, blank=True,
78
+ help_text="Defines a preferred or an alternate stylesheet.")
79
+ type = models.CharField(
80
+ max_length=255, null=True, blank=True,
81
+ help_text="Specifies the media type of the linked document. E.g. 'text/css'.")
82
+ attributes = models.JSONField(
83
+ null=True, blank=True, encoder=DjangoJSONEncoder,
84
+ help_text='More attributes as JSON data. E.g. {"data-name": "value", "id": 42}')
85
+
86
+ def __str__(self):
87
+ return self.href
88
+
89
+
90
+ class Iframe(CMSPlugin):
91
+ """HTML Iframe tag."""
92
+
93
+ src = models.CharField(
94
+ max_length=255, validators=[validate_url_or_path],
95
+ help_text="Specifies the address of the document to embed in the &lt;iframe&gt;.")
96
+ allow = models.CharField(
97
+ max_length=255, null=True, blank=True,
98
+ help_text="Specifies a feature policy for the &lt;iframe&gt;. Form more see "
99
+ "<a href='https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe#allow' target='_blank'>"
100
+ "IFrame attributes.</a>.")
101
+ allow_full_screen = models.BooleanField(
102
+ null=True, blank=True,
103
+ help_text='Set to true if the &lt;iframe&gt; can activate fullscreen mode by calling the requestFullscreen() '
104
+ 'method.'
105
+ )
106
+ allow_payment_request = models.BooleanField(
107
+ null=True, blank=True,
108
+ help_text='Set to true if a cross-origin &lt;iframe&gt; should be allowed to invoke the Payment Request API.'
109
+ )
110
+ height = models.IntegerField(
111
+ null=True, blank=True,
112
+ help_text='Specifies the height of an &lt;iframe&gt;. Default height is 150 pixels.')
113
+ width = models.IntegerField(
114
+ null=True, blank=True,
115
+ help_text='Specifies the width of an &lt;iframe&gt;. Default width is 300 pixels.')
116
+ loading = models.CharField(
117
+ max_length=255, null=True, blank=True, choices=make_opt_choices(LOADING), default=None,
118
+ help_text="Specifies whether a browser should load an iframe immediately or to defer loading of iframes "
119
+ "until some conditions are met.")
120
+ name = models.CharField(
121
+ max_length=255, null=True, blank=True,
122
+ help_text="Specifies the name of an &lt;iframe&gt;.")
123
+ referrer_policy = models.CharField(
124
+ max_length=50, null=True, blank=True, choices=make_opt_choices(SCRIPT_REFERRER_POLICY), default=None,
125
+ help_text="Specifies which referrer information to send when fetching the iframe.")
126
+ sandbox = models.CharField(
127
+ max_length=50, null=True, blank=True, choices=make_opt_choices(SANDBOX), default=None,
128
+ help_text="Enables an extra set of restrictions for the content in an &lt;iframe&gt;.")
129
+ src_doc = models.TextField(
130
+ null=True, blank=True, help_text="Specifies the HTML content of the page to show in the &lt;iframe&gt;."
131
+ )
132
+ attributes = models.JSONField(
133
+ null=True, blank=True, encoder=DjangoJSONEncoder,
134
+ help_text='More attributes as JSON data. E.g. {"data-name": "value", "id": 42}')
135
+
136
+ def __str__(self):
137
+ return self.src
@@ -0,0 +1 @@
1
+ <iframe src="{{ instance.src }}"{% if instance.allow %} allow{% endif %}{% if instance.allow_full_screen is not None %} allowfullscreen="{% if instance.allow_full_screen %}1{% else %}0{% endif %}"{% endif %}{% if instance.allow_payment_request is not None %} allowpaymentrequest="{% if instance.allow_payment_request %}1{% else %}0{% endif %}"{% endif %}{% if instance.height %} height="{{ instance.height }}"{% endif %}{% if instance.width %} width="{{ instance.width }}"{% endif %}{% if instance.loading %} loading="{{ instance.loading }}"{% endif %}{% if instance.name %} name="{{ instance.name }}"{% endif %}{% if instance.referrer_policy %} referrerpolicy="{{ instance.referrer_policy }}"{% endif %}{% if instance.sandbox %} sandbox="{{ instance.sandbox }}"{% endif %}{% if instance.src_doc %} srcdoc="{{ instance.src_doc }}"{% endif %}{% if instance.attributes %}{% for name, value in instance.attributes.items %} {{ name }}="{{ value }}"{% endfor %}{% endif %}></iframe>
@@ -0,0 +1 @@
1
+ <link href="{{ instance.href }}"{% if instance.rel %} rel="{{ instance.rel }}"{% endif %}{% if instance.cross_origin %} crossorigin="{{ instance.cross_origin }}"{% endif %}{% if instance.hreflang %} hreflang="{{ instance.hreflang }}"{% endif %}{% if instance.media %} media="{{ instance.media }}"{% endif %}{% if instance.referrer_policy %} referrerpolicy="{{ instance.referrer_policy }}"{% endif %}{% if instance.sizes %} sizes="{{ instance.sizes }}"{% endif %}{% if instance.title %} title="{{ instance.title }}"{% endif %}{% if instance.type %} type="{{ instance.type }}"{% endif %}{% if instance.attributes %}{% for name, value in instance.attributes.items %} {{ name }}="{{ value }}"{% endfor %}{% endif %}>
@@ -0,0 +1 @@
1
+ <script src="{{ instance.src }}"{% if instance.asyncf %} async{% endif %}{% if instance.cross_origin %} crossorigin="{{ instance.cross_origin }}"{% endif %}{% if instance.defer %} defer{% endif %}{% if instance.integrity %} integrity="{{ instance.integrity }}"{% endif %}{% if instance.referrer_policy %} referrerpolicy="{{ instance.referrer_policy }}"{% endif %}{% if instance.nomodule %} nomodule{% endif %}{% if instance.title %} title="{{ instance.title }}"{% endif %}{% if instance.type %} type="{{ instance.type }}"{% endif %}{% if instance.attributes %}{% for name, value in instance.attributes.items %} {{ name }}="{{ value }}"{% endfor %}{% endif %}></script>
@@ -0,0 +1,8 @@
1
+ def make_choices(items: tuple[str, ...]) -> list[tuple[str, str]]:
2
+ """Make field required choices."""
3
+ return [(item, item) for item in items]
4
+
5
+
6
+ def make_opt_choices(items: tuple[str, ...]) -> list[tuple[str, str]]:
7
+ """Make field optional choices."""
8
+ return [('', '')] + make_choices(items)
@@ -0,0 +1,15 @@
1
+ from django.core.validators import RegexValidator, URLValidator, _lazy_re_compile
2
+ from django.utils.translation import gettext_lazy as _
3
+
4
+ path_validator = RegexValidator(
5
+ _lazy_re_compile(r"^/\w+"),
6
+ message=_("Enter a valid URL or path."),
7
+ code="invalid",
8
+ )
9
+
10
+
11
+ def validate_url_or_path(value: str) -> None:
12
+ """Validate URL or path."""
13
+ if value[:1] == '/':
14
+ return path_validator(value)
15
+ return URLValidator()(value)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: django-cms-qe
3
- Version: 3.2.0
3
+ Version: 3.3.0
4
4
  Summary: Django CMS Quick & Easy provides all important modules to run new page withouta lot of coding. Aims to do it very easily and securely.
5
5
  Home-page: https://websites.pages.nic.cz/django-cms-qe
6
6
  Author: CZ.NIC, z.s.p.o.
@@ -47,7 +47,7 @@ cms_qe/settings/__init__.py,sha256=GJwHXMHwMuGYE-3ZzePJ-26I2WwE8bAIMUDoiTFr0L8,9
47
47
  cms_qe/settings/dev.py,sha256=51CBwiclE8LLoNB2uioIK_L3JhM1yzukQ0gZimkcFqw,1487
48
48
  cms_qe/settings/unittest.py,sha256=folLIMJb1Arh60_Sn0eNQrvIlx0OsAs6v1tDfyRZVuQ,514
49
49
  cms_qe/settings/base/__init__.py,sha256=5yHfne9gPD_xuTaG3voZP23yzuCwROmif2mmKs-hG_A,446
50
- cms_qe/settings/base/app.py,sha256=vAq5Eo2LK6yU19cvbLrpLpWLV_REhdVRs9NfCZGEeu8,3966
50
+ cms_qe/settings/base/app.py,sha256=pmy_0ThkSDNXmEVrWwFpRQ-mjHCvYFoo8YxmFRLG5bM,3988
51
51
  cms_qe/settings/base/auth.py,sha256=axEmEG5UYxyY3EE0keQjGZzkTv2iwxwfULr4LcvZPns,207
52
52
  cms_qe/settings/base/cache.py,sha256=9p6C5lOz1pG-6k15PyvxlShUjBYIbU0ewpA8AX_YFus,297
53
53
  cms_qe/settings/base/cms.py,sha256=8icCNxcEp_KRDyP8-LXB21UurJL4wNysY39whAyt3I4,1855
@@ -3888,6 +3888,17 @@ cms_qe_newsletter/templates/admin/cms_qe_newsletter/mailinglist/change_list.html
3888
3888
  cms_qe_newsletter/templates/cms_qe/newsletter/form.html,sha256=5YsoZlQsxlBfMStROmK8V9T0-w5akjCu3a75GlpO9bk,385
3889
3889
  cms_qe_newsletter/templates/cms_qe/newsletter/newsletter.html,sha256=0YnNGr4hNhAlkM-7ISeE8y1vRhFi7DdjJI_QH_B_ME4,195
3890
3890
  cms_qe_newsletter/templates/cms_qe/newsletter/submitted.html,sha256=mOgMi56fuo3VFGC7P_uIA0XQQ7qAkG130s-WuvmF-n4,51
3891
+ cms_qe_plugins/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3892
+ cms_qe_plugins/attributes.py,sha256=XWLp_Mo3ZQxqUXKOsv1ff-IAX8fnNi2FS_KqdoQT0hQ,760
3893
+ cms_qe_plugins/cms_plugins.py,sha256=MLuIUaeVWMjG8zMqUrM5yqdSlmhgJdJ2T1OMHrvhTHg,683
3894
+ cms_qe_plugins/models.py,sha256=rJ8qKD8q2gp_dfWyXnmbXk3hz71DKoVuvr0fztk_gQ0,6789
3895
+ cms_qe_plugins/utils.py,sha256=7xnvez79gmODczHv_GEiQgvvaeALO2xWzNSKK33HoPw,306
3896
+ cms_qe_plugins/validators.py,sha256=qqLsCB-2kqC5QvWoSG3yqaVJVKvwPgq0QMwTrR3LKoA,445
3897
+ cms_qe_plugins/migrations/0001_initial.py,sha256=O6dBegZWf6DwRKXTz5vx3lNZ-GcBrvGpq94QeVBgo2I,17673
3898
+ cms_qe_plugins/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3899
+ cms_qe_plugins/templates/cms_qe_plugins/iframe.html,sha256=rWJ7kj7lAjKAr2gJMRX1gRTUHBdVcuFJ-ajN2zZhZvE,978
3900
+ cms_qe_plugins/templates/cms_qe_plugins/link.html,sha256=zzAr1dAWckbPEw5RnkmFKdIZDnbKqVs_g47wbETusLs,713
3901
+ cms_qe_plugins/templates/cms_qe_plugins/script.html,sha256=PnOgFjXxtzOEKzGRQQnTdKiDTEzENl-_q14WYrbIYJ0,669
3891
3902
  cms_qe_table/__init__.py,sha256=0eiVSkglZ6A-QLBnGXQdTlysM6dj2kfTc6scFcUGGVA,1084
3892
3903
  cms_qe_table/cms_plugins.py,sha256=dR8b7h_xOJnQ4CDetxrfOiv1tfekhdnpe4KbKqasLi0,1065
3893
3904
  cms_qe_table/exceptions.py,sha256=D9jeyKebnha1lObxS-eJhDeIYLobqlQCLieqg5jPkEU,349
@@ -3940,8 +3951,6 @@ cms_qe_video/templates/cms_qe/video/video_source_file.html,sha256=QJF5fs88s9Fznp
3940
3951
  cms_qe_video/templates/cms_qe/video/video_widget.html,sha256=Yumciq6bGlAYI1lYx5j9V6IF8QYrncNYygPTkXEz6Wk,925
3941
3952
  cms_qe_video/templatetags/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3942
3953
  cms_qe_video/templatetags/cms_qe_video.py,sha256=NR_mGv91J0rEreZrQjCzaaXSrZsKvrSas12wMJ-Dg24,1168
3943
- django_mail_backends/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3944
- django_mail_backends/filebased.py,sha256=tsvMFFlm7-U5krIly53DArYZmrDrNZwQowKHScE8qQ4,612
3945
3954
  example/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3946
3955
  example/urls.py,sha256=H-IJsRGFVZGw6FD9gvK-0B0dLeSOsduziHvDvcHCQZ0,399
3947
3956
  example/wsgi.py,sha256=lCKhvtFZlorSIA8qYEqc3pZ1Oflrz_Tc696MWJ62ue4,396
@@ -3962,8 +3971,8 @@ test_selenium/pages/cms/__init__.py,sha256=_qe4YZYaQbrXp7Szmmeo4TUSkXlE5Rozu8E3t
3962
3971
  test_selenium/pages/cms/login.py,sha256=UPzJQcYff8NUAT4nvmfQoJQxzOJyPrJ_cKtH35NVfNg,521
3963
3972
  test_selenium/pages/cms/page.py,sha256=YQnpZkopfVnhoyQKpRDGqjNeV6xUl-pEHjEcZ9HRiPk,489
3964
3973
  test_selenium/pages/cms/wizard.py,sha256=yatbXH-rf1ap4O1hY0I13WikM3zkm_NrAiSK6bqENIU,545
3965
- django_cms_qe-3.2.0.dist-info/LICENSE,sha256=5wLaeUil0gfU9p8C4zn2Yu_PvZBNieUoYl0z9FcFWdA,1521
3966
- django_cms_qe-3.2.0.dist-info/METADATA,sha256=6MBxVvDvwZR8z0sS-gYogsECKcYxogAu9YMsCNReG1o,4677
3967
- django_cms_qe-3.2.0.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
3968
- django_cms_qe-3.2.0.dist-info/top_level.txt,sha256=sns93tUvzAUoyPpolDHe0Orka1l44A4BJnYFko7EIKU,178
3969
- django_cms_qe-3.2.0.dist-info/RECORD,,
3974
+ django_cms_qe-3.3.0.dist-info/LICENSE,sha256=5wLaeUil0gfU9p8C4zn2Yu_PvZBNieUoYl0z9FcFWdA,1521
3975
+ django_cms_qe-3.3.0.dist-info/METADATA,sha256=IqUIoCRDoEpA_bKnEWxPZK-8Fe2Phz-Ugxszg5B3Oco,4677
3976
+ django_cms_qe-3.3.0.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
3977
+ django_cms_qe-3.3.0.dist-info/top_level.txt,sha256=T4dauFwJy7FmxCy7WoQI3pPwiDessNB2LkfOAP76ssE,172
3978
+ django_cms_qe-3.3.0.dist-info/RECORD,,
@@ -5,9 +5,9 @@ cms_qe_breadcrumb
5
5
  cms_qe_i18n
6
6
  cms_qe_menu
7
7
  cms_qe_newsletter
8
+ cms_qe_plugins
8
9
  cms_qe_table
9
10
  cms_qe_test
10
11
  cms_qe_video
11
- django_mail_backends
12
12
  example
13
13
  test_selenium
@@ -1,17 +0,0 @@
1
- # EMAIL_BACKEND = 'django.core.mail.backends.filebased.EmailBackend'
2
- # EMAIL_BACKEND = 'django_mail_backends.filebased.EmailBackend'
3
- import datetime
4
- import os
5
-
6
- from django.core.mail.backends.filebased import EmailBackend as DjangoEmailBackend
7
-
8
-
9
- class EmailBackend(DjangoEmailBackend):
10
-
11
- def _get_filename(self):
12
- """Return a unique file name."""
13
- if self._fname is None:
14
- timestamp = datetime.datetime.now().strftime("%Y%m%d-%H%M%S")
15
- fname = "%s-%s.eml" % (timestamp, abs(id(self)))
16
- self._fname = os.path.join(self.file_path, fname)
17
- return self._fname
File without changes