django-camomilla-cms 6.0.0b16__py2.py3-none-any.whl → 6.0.0b17__py2.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.
- camomilla/__init__.py +1 -1
- camomilla/contrib/modeltranslation/hvad_migration.py +9 -9
- camomilla/dynamic_pages_urls.py +6 -2
- camomilla/managers/pages.py +87 -2
- camomilla/model_api.py +6 -4
- camomilla/models/menu.py +9 -4
- camomilla/models/page.py +178 -117
- camomilla/openapi/schema.py +15 -10
- camomilla/redirects.py +10 -0
- camomilla/serializers/base/__init__.py +4 -4
- camomilla/serializers/fields/__init__.py +5 -17
- camomilla/serializers/fields/related.py +5 -3
- camomilla/serializers/mixins/__init__.py +23 -240
- camomilla/serializers/mixins/fields.py +20 -0
- camomilla/serializers/mixins/filter_fields.py +9 -8
- camomilla/serializers/mixins/json.py +34 -0
- camomilla/serializers/mixins/language.py +32 -0
- camomilla/serializers/mixins/nesting.py +35 -0
- camomilla/serializers/mixins/optimize.py +91 -0
- camomilla/serializers/mixins/ordering.py +34 -0
- camomilla/serializers/mixins/page.py +58 -0
- camomilla/{contrib/rest_framework/serializer.py → serializers/mixins/translation.py} +16 -56
- camomilla/serializers/utils.py +3 -3
- camomilla/serializers/validators.py +6 -2
- camomilla/settings.py +10 -2
- camomilla/storages/default.py +7 -1
- camomilla/templates/defaults/parts/menu.html +1 -1
- camomilla/templatetags/menus.py +3 -0
- camomilla/theme/__init__.py +1 -1
- camomilla/theme/{admin.py → admin/__init__.py} +22 -20
- camomilla/theme/admin/pages.py +46 -0
- camomilla/theme/admin/translations.py +13 -0
- camomilla/theme/apps.py +1 -5
- camomilla/translation.py +7 -1
- camomilla/urls.py +2 -5
- camomilla/utils/query_parser.py +42 -23
- camomilla/utils/translation.py +47 -5
- camomilla/views/base/__init__.py +35 -5
- camomilla/views/medias.py +1 -1
- camomilla/views/mixins/__init__.py +17 -76
- camomilla/views/mixins/bulk_actions.py +22 -0
- camomilla/views/mixins/language.py +33 -0
- camomilla/views/mixins/optimize.py +18 -0
- camomilla/views/mixins/pagination.py +11 -8
- camomilla/views/mixins/permissions.py +6 -0
- camomilla/views/pages.py +12 -2
- {django_camomilla_cms-6.0.0b16.dist-info → django_camomilla_cms-6.0.0b17.dist-info}/METADATA +23 -16
- {django_camomilla_cms-6.0.0b16.dist-info → django_camomilla_cms-6.0.0b17.dist-info}/RECORD +60 -43
- {django_camomilla_cms-6.0.0b16.dist-info → django_camomilla_cms-6.0.0b17.dist-info}/WHEEL +1 -1
- tests/test_camomilla_filters.py +1 -1
- tests/test_media.py +98 -65
- tests/test_menu.py +97 -0
- tests/test_model_api_register.py +393 -0
- tests/test_pages.py +343 -0
- tests/test_query_parser.py +1 -2
- tests/test_templates_context.py +111 -0
- tests/utils/api.py +0 -1
- tests/utils/media.py +9 -0
- camomilla/contrib/rest_framework/__init__.py +0 -0
- camomilla/serializers/fields/json.py +0 -48
- {django_camomilla_cms-6.0.0b16.dist-info → django_camomilla_cms-6.0.0b17.dist-info/licenses}/LICENSE +0 -0
- {django_camomilla_cms-6.0.0b16.dist-info → django_camomilla_cms-6.0.0b17.dist-info}/top_level.txt +0 -0
tests/test_pages.py
ADDED
@@ -0,0 +1,343 @@
|
|
1
|
+
import pytest
|
2
|
+
from django.test import TestCase
|
3
|
+
from rest_framework.test import APIClient
|
4
|
+
from .utils.api import login_superuser
|
5
|
+
from camomilla.models import Page
|
6
|
+
from camomilla.models.page import UrlRedirect
|
7
|
+
from datetime import datetime, timedelta
|
8
|
+
|
9
|
+
|
10
|
+
class PagesTestCase(TestCase):
|
11
|
+
def setUp(self):
|
12
|
+
self.client = APIClient()
|
13
|
+
token = login_superuser()
|
14
|
+
self.client.credentials(HTTP_AUTHORIZATION='Token ' + token)
|
15
|
+
|
16
|
+
@pytest.mark.django_db
|
17
|
+
def test_pages_api_no_access(self):
|
18
|
+
client = APIClient()
|
19
|
+
response = client.post("/api/camomilla/pages/")
|
20
|
+
assert response.status_code == 401
|
21
|
+
|
22
|
+
@pytest.mark.django_db
|
23
|
+
def test_pages_api_crud(self):
|
24
|
+
# Create page
|
25
|
+
response = self.client.post(
|
26
|
+
"/api/camomilla/pages/",
|
27
|
+
{
|
28
|
+
"translations": {
|
29
|
+
"it": {
|
30
|
+
"title": "title_page_1",
|
31
|
+
}
|
32
|
+
}
|
33
|
+
},
|
34
|
+
format='json'
|
35
|
+
)
|
36
|
+
|
37
|
+
assert response.status_code == 201
|
38
|
+
assert len(Page.objects.all()) == 1
|
39
|
+
page = Page.objects.first()
|
40
|
+
assert page.id == 1
|
41
|
+
assert page.title_it == "title_page_1"
|
42
|
+
assert page.url_node.id == 1
|
43
|
+
|
44
|
+
response = self.client.post(
|
45
|
+
"/api/camomilla/pages/",
|
46
|
+
{
|
47
|
+
"title_it": "title_page_2",
|
48
|
+
}
|
49
|
+
)
|
50
|
+
|
51
|
+
assert response.status_code == 201
|
52
|
+
assert len(Page.objects.all()) == 2
|
53
|
+
page = Page.objects.last()
|
54
|
+
assert page.id == 2
|
55
|
+
assert page.title_it == "title_page_2"
|
56
|
+
assert page.url_node.id == 2
|
57
|
+
|
58
|
+
# Update page
|
59
|
+
response = self.client.patch(
|
60
|
+
"/api/camomilla/pages/2/",
|
61
|
+
{
|
62
|
+
"translations": {
|
63
|
+
"it": {
|
64
|
+
"title": "title_page_2_updated",
|
65
|
+
}
|
66
|
+
}
|
67
|
+
},
|
68
|
+
format='json'
|
69
|
+
)
|
70
|
+
|
71
|
+
assert response.status_code == 200
|
72
|
+
assert len(Page.objects.all()) == 2
|
73
|
+
page = Page.objects.last()
|
74
|
+
assert page.id == 2
|
75
|
+
assert page.title_it == "title_page_2_updated"
|
76
|
+
|
77
|
+
# Read page
|
78
|
+
response = self.client.get("/api/camomilla/pages/2/")
|
79
|
+
|
80
|
+
assert response.status_code == 200
|
81
|
+
assert response.json()['id'] == 2
|
82
|
+
assert response.json()['title'] == "title_page_2_updated"
|
83
|
+
|
84
|
+
# Read pages
|
85
|
+
response = self.client.get("/api/camomilla/pages/")
|
86
|
+
|
87
|
+
assert response.status_code == 200
|
88
|
+
assert response.json()[0]['id'] == 1
|
89
|
+
assert response.json()[0]['title'] == "title_page_1"
|
90
|
+
assert response.json()[1]['id'] == 2
|
91
|
+
assert response.json()[1]['title'] == "title_page_2_updated"
|
92
|
+
|
93
|
+
# Delete page
|
94
|
+
response = self.client.delete("/api/camomilla/pages/2/")
|
95
|
+
|
96
|
+
assert response.status_code == 204
|
97
|
+
assert len(Page.objects.all()) == 1
|
98
|
+
page = Page.objects.last()
|
99
|
+
assert page.id == 1
|
100
|
+
assert page.title_it == "title_page_1"
|
101
|
+
|
102
|
+
@pytest.mark.django_db
|
103
|
+
def test_pages_url_nodes(self):
|
104
|
+
# Create page with automatic url creation
|
105
|
+
response = self.client.post(
|
106
|
+
"/api/camomilla/pages/",
|
107
|
+
{
|
108
|
+
"title_en": "title_page_1",
|
109
|
+
"title_it": "titolo_pagina_1",
|
110
|
+
}
|
111
|
+
)
|
112
|
+
|
113
|
+
assert response.status_code == 201
|
114
|
+
|
115
|
+
# EN automatic url creation
|
116
|
+
response = self.client.get("/api/camomilla/pages/1/?language=en")
|
117
|
+
assert response.json()['autopermalink'] == True
|
118
|
+
assert response.json()['permalink'] == "/title_page_1"
|
119
|
+
# IT automatic url creation
|
120
|
+
response = self.client.get("/api/camomilla/pages/1/?language=it")
|
121
|
+
assert response.json()['autopermalink'] == True
|
122
|
+
assert response.json()['permalink'] == "/titolo_pagina_1"
|
123
|
+
|
124
|
+
# Create page with manual url creation
|
125
|
+
response = self.client.post(
|
126
|
+
"/api/camomilla/pages/",
|
127
|
+
{
|
128
|
+
"translations": {
|
129
|
+
"it": {
|
130
|
+
"title": "titolo_pagina_2",
|
131
|
+
"permalink": "permalink_manuale_it_2",
|
132
|
+
"autopermalink": False
|
133
|
+
},
|
134
|
+
"en": {
|
135
|
+
"title": "title_page_2",
|
136
|
+
"permalink": "permalink_manual_en_2",
|
137
|
+
"autopermalink": False
|
138
|
+
}
|
139
|
+
}
|
140
|
+
},
|
141
|
+
format='json'
|
142
|
+
)
|
143
|
+
assert response.status_code == 201
|
144
|
+
|
145
|
+
# EN manual url creation
|
146
|
+
response = self.client.get("/api/camomilla/pages/2/?language=en")
|
147
|
+
assert response.json()['autopermalink'] == False
|
148
|
+
assert response.json()['permalink'] == "/permalink_manual_en_2"
|
149
|
+
# IT manual url creation
|
150
|
+
response = self.client.get("/api/camomilla/pages/2/?language=it")
|
151
|
+
assert response.json()['autopermalink'] == False
|
152
|
+
assert response.json()['permalink'] == "/permalink_manuale_it_2"
|
153
|
+
|
154
|
+
# Create page with a parent page with automatic url creation
|
155
|
+
response = self.client.post(
|
156
|
+
"/api/camomilla/pages/",
|
157
|
+
{
|
158
|
+
"title_en": "title_page_3",
|
159
|
+
"title_it": "titolo_pagina_3",
|
160
|
+
"parent_page": 2
|
161
|
+
}
|
162
|
+
)
|
163
|
+
assert response.status_code == 201
|
164
|
+
|
165
|
+
# EN parent page with automatic url creation
|
166
|
+
response = self.client.get("/api/camomilla/pages/3/?language=en")
|
167
|
+
assert response.json()['autopermalink'] == True
|
168
|
+
assert response.json()['permalink'] == "//permalink_manual_en_2/title_page_3"
|
169
|
+
# IT parent page with automatic url creation
|
170
|
+
response = self.client.get("/api/camomilla/pages/3/?language=it")
|
171
|
+
assert response.json()['autopermalink'] == True
|
172
|
+
assert response.json()['permalink'] == "//permalink_manuale_it_2/titolo_pagina_3"
|
173
|
+
|
174
|
+
# Check url uniqueness and consistency EN
|
175
|
+
response = self.client.post(
|
176
|
+
"/api/camomilla/pages/",
|
177
|
+
{
|
178
|
+
"autopermalink_en": False,
|
179
|
+
"permalink_en": "permalink_manual_en_2",
|
180
|
+
}
|
181
|
+
)
|
182
|
+
|
183
|
+
# Client error when url check uniqueness and consistency fail
|
184
|
+
assert response.status_code == 400
|
185
|
+
assert response.data['permalink_en'][0] == "There is an other page with same permalink."
|
186
|
+
|
187
|
+
# Check url uniqueness and consistency IT
|
188
|
+
response = self.client.post(
|
189
|
+
"/api/camomilla/pages/",
|
190
|
+
{
|
191
|
+
"translations": {
|
192
|
+
"it": {
|
193
|
+
"autopermalink": False,
|
194
|
+
"permalink": "permalink_manuale_it_2",
|
195
|
+
}
|
196
|
+
}
|
197
|
+
},
|
198
|
+
format='json'
|
199
|
+
)
|
200
|
+
|
201
|
+
# Client error when url check uniqueness and consistency fail
|
202
|
+
assert response.status_code == 400
|
203
|
+
assert response.data['permalink_it'][0] == "There is an other page with same permalink."
|
204
|
+
|
205
|
+
@pytest.mark.django_db
|
206
|
+
def test_pages_url_nodes_navigation(self):
|
207
|
+
#Test the camomilla.dynamic_pages_url handler for navigating and rendering UrlNodes
|
208
|
+
self.client.post(
|
209
|
+
"/api/camomilla/pages/",
|
210
|
+
{
|
211
|
+
"autopermalink_en": False,
|
212
|
+
"permalink_en": "permalink_4_en",
|
213
|
+
"status_en": "PUB",
|
214
|
+
"autopermalink_it": False,
|
215
|
+
"permalink_it": "permalink_4_it",
|
216
|
+
"status_it": "PUB",
|
217
|
+
}
|
218
|
+
)
|
219
|
+
|
220
|
+
response = self.client.get("/permalink_4_en/")
|
221
|
+
assert response.status_code == 200
|
222
|
+
response = self.client.get("/it/permalink_4_it/")
|
223
|
+
assert response.status_code == 200
|
224
|
+
|
225
|
+
#Test draft - published - planned and ?preview=true
|
226
|
+
self.client.post(
|
227
|
+
"/api/camomilla/pages/",
|
228
|
+
{
|
229
|
+
"translations": {
|
230
|
+
"it": {
|
231
|
+
"autopermalink": False,
|
232
|
+
"permalink": "permalink_5_it",
|
233
|
+
"status": "PLA",
|
234
|
+
},
|
235
|
+
"en": {
|
236
|
+
"autopermalink": False,
|
237
|
+
"permalink": "permalink_5_en",
|
238
|
+
"status": "DRF",
|
239
|
+
}
|
240
|
+
}
|
241
|
+
},
|
242
|
+
format='json'
|
243
|
+
)
|
244
|
+
|
245
|
+
response = self.client.get("/permalink_5_en/")
|
246
|
+
assert response.status_code == 404
|
247
|
+
response = self.client.get("/permalink_5_en/?preview=true")
|
248
|
+
assert response.status_code == 200
|
249
|
+
response = self.client.get("/it/permalink_5_it/")
|
250
|
+
assert response.status_code == 404
|
251
|
+
|
252
|
+
self.client.patch(
|
253
|
+
"/api/camomilla/pages/2/",
|
254
|
+
{
|
255
|
+
"publication_date": (datetime.now() - timedelta(1)).strftime('%Y-%m-%d') + " 00:00:00",
|
256
|
+
}
|
257
|
+
)
|
258
|
+
|
259
|
+
response = self.client.get("/it/permalink_5_it/")
|
260
|
+
assert response.status_code == 200
|
261
|
+
|
262
|
+
@pytest.mark.django_db
|
263
|
+
def test_pages_url_nodes_navigation_redirects(self):
|
264
|
+
#Test the camomilla.dynamic_pages_url handler for navigating and rendering UrlNodes
|
265
|
+
self.client.post(
|
266
|
+
"/api/camomilla/pages/",
|
267
|
+
{
|
268
|
+
"translations": {
|
269
|
+
"it": {
|
270
|
+
"autopermalink": False,
|
271
|
+
"permalink": "permalink_6_it",
|
272
|
+
"status": "PUB",
|
273
|
+
},
|
274
|
+
"en": {
|
275
|
+
"autopermalink": False,
|
276
|
+
"permalink": "permalink_6_en",
|
277
|
+
"status": "PUB",
|
278
|
+
}
|
279
|
+
}
|
280
|
+
},
|
281
|
+
format='json'
|
282
|
+
)
|
283
|
+
|
284
|
+
#EN Insert Moved Permanently Redirect
|
285
|
+
url_redirect = UrlRedirect.objects.create(
|
286
|
+
language_code='en',
|
287
|
+
from_url='/redirecting_1',
|
288
|
+
to_url='/redirected_1',
|
289
|
+
url_node_id=1
|
290
|
+
)
|
291
|
+
|
292
|
+
response = self.client.get("/redirecting_1/")
|
293
|
+
assert response.status_code == 301
|
294
|
+
assert response.url == '/redirected_1/'
|
295
|
+
|
296
|
+
#EN Change to Moved Temporarily Redirect
|
297
|
+
url_redirect.permanent = False
|
298
|
+
url_redirect.save()
|
299
|
+
response = self.client.get("/redirecting_1/")
|
300
|
+
assert response.status_code == 302
|
301
|
+
|
302
|
+
|
303
|
+
#IT Insert Moved Permanently Redirect
|
304
|
+
url_redirect = UrlRedirect.objects.create(
|
305
|
+
language_code='it',
|
306
|
+
from_url='/urlreindirizzamento_1',
|
307
|
+
to_url='/urlreindirizzato_1',
|
308
|
+
url_node_id=1
|
309
|
+
)
|
310
|
+
|
311
|
+
response = self.client.get("/it/urlreindirizzamento_1/")
|
312
|
+
assert response.status_code == 301
|
313
|
+
assert response.url == '/it/urlreindirizzato_1/'
|
314
|
+
|
315
|
+
#IT Change to Moved Temporarily Redirect
|
316
|
+
url_redirect.permanent = False
|
317
|
+
url_redirect.save()
|
318
|
+
response = self.client.get("/it/urlreindirizzamento_1/")
|
319
|
+
assert response.status_code == 302
|
320
|
+
|
321
|
+
# Test auto redirect after permalink change
|
322
|
+
self.client.patch(
|
323
|
+
"/api/camomilla/pages/1/",
|
324
|
+
{
|
325
|
+
"translations": {
|
326
|
+
"it": {
|
327
|
+
"permalink": "permalink_6_it_changed",
|
328
|
+
},
|
329
|
+
"en": {
|
330
|
+
"permalink": "permalink_6_en_changed",
|
331
|
+
}
|
332
|
+
}
|
333
|
+
},
|
334
|
+
format='json'
|
335
|
+
)
|
336
|
+
|
337
|
+
response = self.client.get("/permalink_6_en/")
|
338
|
+
assert response.status_code == 301
|
339
|
+
assert response.url == '/permalink_6_en_changed/'
|
340
|
+
|
341
|
+
response = self.client.get("/it/permalink_6_it/")
|
342
|
+
assert response.status_code == 301
|
343
|
+
assert response.url == '/it/permalink_6_it_changed/'
|
tests/test_query_parser.py
CHANGED
@@ -4,6 +4,7 @@ from camomilla.utils.query_parser import (
|
|
4
4
|
ConditionParser,
|
5
5
|
)
|
6
6
|
|
7
|
+
|
7
8
|
@pytest.mark.parametrize(
|
8
9
|
"query, expected_q",
|
9
10
|
[
|
@@ -55,5 +56,3 @@ def test_condition_parser(query, expected_q):
|
|
55
56
|
parser = ConditionParser(query)
|
56
57
|
q_object = parser.parse_to_q()
|
57
58
|
assert q_object.__str__() == expected_q.__str__()
|
58
|
-
|
59
|
-
|
@@ -0,0 +1,111 @@
|
|
1
|
+
import pytest
|
2
|
+
import json
|
3
|
+
import re
|
4
|
+
from django.test import TestCase
|
5
|
+
from rest_framework.test import APIClient
|
6
|
+
from .utils.api import login_superuser
|
7
|
+
from .utils.media import load_asset_and_remove_media
|
8
|
+
|
9
|
+
class TemoplateContextTestCase(TestCase):
|
10
|
+
def setUp(self):
|
11
|
+
self.client = APIClient()
|
12
|
+
token = login_superuser()
|
13
|
+
self.client.credentials(HTTP_AUTHORIZATION='Token ' + token)
|
14
|
+
|
15
|
+
@pytest.mark.django_db
|
16
|
+
def test_page_context_template_based(self):
|
17
|
+
# Create page with custom context template
|
18
|
+
response = self.client.post(
|
19
|
+
"/api/camomilla/pages/",
|
20
|
+
{
|
21
|
+
"title_en": "Page custom context template",
|
22
|
+
"autopermalink_en": False,
|
23
|
+
"permalink_en": "permalink_context_template",
|
24
|
+
"template": "website/page_context_template_based.html",
|
25
|
+
"status_en": "PUB",
|
26
|
+
},
|
27
|
+
format="multipart",
|
28
|
+
)
|
29
|
+
assert response.status_code == 201
|
30
|
+
|
31
|
+
# Create media for custom context
|
32
|
+
asset = load_asset_and_remove_media("10595073.png")
|
33
|
+
response = self.client.post(
|
34
|
+
"/api/camomilla/media/",
|
35
|
+
{
|
36
|
+
"file": asset,
|
37
|
+
"data": json.dumps({"translations": {"en": {"alt_text": "Test media", "title": "Test media", "description": "Description media"}}}),
|
38
|
+
},
|
39
|
+
format="multipart",
|
40
|
+
)
|
41
|
+
assert response.status_code == 201
|
42
|
+
|
43
|
+
response = self.client.get("/permalink_context_template/")
|
44
|
+
assert response.status_code == 200
|
45
|
+
assert re.sub(r'[\s+]', '', response.content.decode()) == '<!DOCTYPEhtml><html><body><h1>Titlepageforpagecontexttemplatebased</h1><p>Contentpageforpagecontexttemplatebased</p><ul><li>Testmedia</li></ul></body></html>'
|
46
|
+
|
47
|
+
|
48
|
+
@pytest.mark.django_db
|
49
|
+
def test_model_context_template_based(self):
|
50
|
+
# Create page with custom context template
|
51
|
+
response = self.client.post(
|
52
|
+
"/api/camomilla/pages/",
|
53
|
+
{
|
54
|
+
"title_en": "Page custom context template",
|
55
|
+
"autopermalink_en": False,
|
56
|
+
"permalink_en": "permalink_context_template",
|
57
|
+
"template": "website/page_context_model_based.html",
|
58
|
+
"status_en": "PUB",
|
59
|
+
},
|
60
|
+
format="multipart",
|
61
|
+
)
|
62
|
+
assert response.status_code == 201
|
63
|
+
|
64
|
+
# Create media for custom context
|
65
|
+
asset = load_asset_and_remove_media("10595073.png")
|
66
|
+
response = self.client.post(
|
67
|
+
"/api/camomilla/media/",
|
68
|
+
{
|
69
|
+
"file": asset,
|
70
|
+
"data": json.dumps({"translations": {"en": {"alt_text": "Test media", "title": "Test media", "description": "Description media"}}}),
|
71
|
+
},
|
72
|
+
format="multipart",
|
73
|
+
)
|
74
|
+
assert response.status_code == 201
|
75
|
+
|
76
|
+
response = self.client.get("/permalink_context_template/")
|
77
|
+
assert response.status_code == 200
|
78
|
+
assert re.sub(r'[\s+]', '', response.content.decode()) == '<!DOCTYPEhtml><html><body><h1>Titlepageforpagecontextmodelbased</h1><p>Contentpageforpagecontextmodelbased</p><ul><li>Testmedia</li></ul></body></html>'
|
79
|
+
|
80
|
+
|
81
|
+
@pytest.mark.django_db
|
82
|
+
def test_mixed_context_template(self):
|
83
|
+
# Create page with custom context template
|
84
|
+
response = self.client.post(
|
85
|
+
"/api/camomilla/pages/",
|
86
|
+
{
|
87
|
+
"title_en": "Page custom context template",
|
88
|
+
"autopermalink_en": False,
|
89
|
+
"permalink_en": "permalink_context_template",
|
90
|
+
"template": "website/page_context_mixed.html",
|
91
|
+
"status_en": "PUB",
|
92
|
+
},
|
93
|
+
format="multipart",
|
94
|
+
)
|
95
|
+
assert response.status_code == 201
|
96
|
+
|
97
|
+
# Create media for custom context
|
98
|
+
asset = load_asset_and_remove_media("10595073.png")
|
99
|
+
response = self.client.post(
|
100
|
+
"/api/camomilla/media/",
|
101
|
+
{
|
102
|
+
"file": asset,
|
103
|
+
"data": json.dumps({"translations": {"en": {"alt_text": "Test media", "title": "Test media", "description": "Description media"}}}),
|
104
|
+
},
|
105
|
+
format="multipart",
|
106
|
+
)
|
107
|
+
assert response.status_code == 201
|
108
|
+
|
109
|
+
response = self.client.get("/permalink_context_template/")
|
110
|
+
assert response.status_code == 200
|
111
|
+
assert re.sub(r'[\s+]', '', response.content.decode()) == '<!DOCTYPEhtml><html><body><!--Templatecontext--><h1>Titlepageforpagecontexttemplatebased</h1><p>Contentpageforpagecontexttemplatebased</p><ul><li>Testmedia</li></ul><!--Modelcontext--><h1>Titlepageforpagecontextmodelbased</h1><p>Contentpageforpagecontextmodelbased</p><ul><li>Testmedia</li></ul></body></html>'
|
tests/utils/api.py
CHANGED
tests/utils/media.py
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
import os
|
2
|
+
from tests.fixtures import load_asset
|
3
|
+
from django.conf import settings
|
4
|
+
|
5
|
+
def load_asset_and_remove_media(filename):
|
6
|
+
asset = load_asset(filename)
|
7
|
+
if os.path.exists(f"{settings.MEDIA_ROOT}/{filename}"):
|
8
|
+
os.remove(f"{settings.MEDIA_ROOT}/{filename}")
|
9
|
+
return asset
|
File without changes
|
@@ -1,48 +0,0 @@
|
|
1
|
-
from pydantic import TypeAdapter, ValidationError
|
2
|
-
from rest_framework import serializers
|
3
|
-
from rest_framework.utils import model_meta
|
4
|
-
from typing import TYPE_CHECKING, Any, Union, Dict, List
|
5
|
-
|
6
|
-
from camomilla.utils.setters import pointed_setter
|
7
|
-
|
8
|
-
if TYPE_CHECKING:
|
9
|
-
from structured.pydantic.models import BaseModel
|
10
|
-
|
11
|
-
|
12
|
-
class StructuredJSONField(serializers.JSONField):
|
13
|
-
"""
|
14
|
-
This field allows to serialize and deserialize structured data.
|
15
|
-
"""
|
16
|
-
|
17
|
-
schema: Union["BaseModel", TypeAdapter] = None
|
18
|
-
|
19
|
-
def __init__(self, **kwargs):
|
20
|
-
self.schema = kwargs.pop("schema", None)
|
21
|
-
super().__init__(**kwargs)
|
22
|
-
|
23
|
-
def bind(self, field_name, parent):
|
24
|
-
if self.schema is None and isinstance(parent, serializers.ModelSerializer):
|
25
|
-
info = model_meta.get_field_info(parent.Meta.model)
|
26
|
-
field = info.fields[field_name]
|
27
|
-
self.schema = field.schema
|
28
|
-
self.many = field.many
|
29
|
-
self.json_schema = field.schema.json_schema()
|
30
|
-
super().bind(field_name, parent)
|
31
|
-
|
32
|
-
def to_representation(self, instance: Union["BaseModel", List["BaseModel"]]):
|
33
|
-
if isinstance(instance, list) and self.many:
|
34
|
-
return super().to_representation(
|
35
|
-
self.schema.dump_python(instance, exclude_unset=True)
|
36
|
-
)
|
37
|
-
return super().to_representation(instance.model_dump(exclude_unset=True))
|
38
|
-
|
39
|
-
def to_internal_value(self, data: Union[list, dict]):
|
40
|
-
try:
|
41
|
-
return self.schema.validate_python(super().to_internal_value(data))
|
42
|
-
except ValidationError as e:
|
43
|
-
drf_error: Union[list, Dict[str, Any]] = [] if self.many else {}
|
44
|
-
for error in e.errors():
|
45
|
-
pointed_setter(
|
46
|
-
drf_error, ".".join([str(x) for x in error["loc"]]), [error["msg"]]
|
47
|
-
)
|
48
|
-
raise serializers.ValidationError(drf_error)
|
{django_camomilla_cms-6.0.0b16.dist-info → django_camomilla_cms-6.0.0b17.dist-info/licenses}/LICENSE
RENAMED
File without changes
|
{django_camomilla_cms-6.0.0b16.dist-info → django_camomilla_cms-6.0.0b17.dist-info}/top_level.txt
RENAMED
File without changes
|