django-camomilla-cms 6.0.0b15__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.
Files changed (72) hide show
  1. camomilla/__init__.py +1 -1
  2. camomilla/contrib/modeltranslation/hvad_migration.py +9 -9
  3. camomilla/dynamic_pages_urls.py +6 -2
  4. camomilla/managers/pages.py +93 -8
  5. camomilla/model_api.py +14 -7
  6. camomilla/models/media.py +1 -1
  7. camomilla/models/menu.py +10 -4
  8. camomilla/models/page.py +189 -127
  9. camomilla/openapi/schema.py +17 -8
  10. camomilla/redirects.py +10 -0
  11. camomilla/serializers/base/__init__.py +6 -4
  12. camomilla/serializers/fields/__init__.py +5 -17
  13. camomilla/serializers/fields/related.py +10 -4
  14. camomilla/serializers/mixins/__init__.py +23 -195
  15. camomilla/serializers/mixins/fields.py +20 -0
  16. camomilla/serializers/mixins/filter_fields.py +57 -0
  17. camomilla/serializers/mixins/json.py +34 -0
  18. camomilla/serializers/mixins/language.py +32 -0
  19. camomilla/serializers/mixins/nesting.py +35 -0
  20. camomilla/serializers/mixins/optimize.py +91 -0
  21. camomilla/serializers/mixins/ordering.py +34 -0
  22. camomilla/serializers/mixins/page.py +58 -0
  23. camomilla/{contrib/rest_framework/serializer.py → serializers/mixins/translation.py} +16 -56
  24. camomilla/serializers/utils.py +5 -3
  25. camomilla/serializers/validators.py +6 -2
  26. camomilla/settings.py +10 -2
  27. camomilla/storages/default.py +12 -0
  28. camomilla/storages/optimize.py +2 -2
  29. camomilla/storages/overwrite.py +2 -2
  30. camomilla/templates/defaults/parts/menu.html +1 -1
  31. camomilla/templatetags/menus.py +3 -0
  32. camomilla/theme/__init__.py +1 -1
  33. camomilla/theme/{admin.py → admin/__init__.py} +22 -20
  34. camomilla/theme/admin/pages.py +46 -0
  35. camomilla/theme/admin/translations.py +13 -0
  36. camomilla/theme/apps.py +1 -5
  37. camomilla/translation.py +7 -1
  38. camomilla/urls.py +2 -5
  39. camomilla/utils/query_parser.py +167 -0
  40. camomilla/utils/translation.py +47 -5
  41. camomilla/views/base/__init__.py +35 -5
  42. camomilla/views/medias.py +1 -1
  43. camomilla/views/menus.py +0 -2
  44. camomilla/views/mixins/__init__.py +17 -69
  45. camomilla/views/mixins/bulk_actions.py +22 -0
  46. camomilla/views/mixins/language.py +33 -0
  47. camomilla/views/mixins/optimize.py +18 -0
  48. camomilla/views/mixins/pagination.py +12 -18
  49. camomilla/views/mixins/permissions.py +6 -0
  50. camomilla/views/pages.py +12 -2
  51. {django_camomilla_cms-6.0.0b15.dist-info → django_camomilla_cms-6.0.0b17.dist-info}/METADATA +23 -16
  52. django_camomilla_cms-6.0.0b17.dist-info/RECORD +132 -0
  53. {django_camomilla_cms-6.0.0b15.dist-info → django_camomilla_cms-6.0.0b17.dist-info}/WHEEL +1 -1
  54. tests/fixtures/__init__.py +17 -0
  55. tests/test_api.py +2 -11
  56. tests/test_camomilla_filters.py +7 -13
  57. tests/test_media.py +113 -0
  58. tests/test_menu.py +97 -0
  59. tests/test_model_api.py +68 -0
  60. tests/test_model_api_permissions.py +39 -0
  61. tests/test_model_api_register.py +393 -0
  62. tests/test_pages.py +343 -0
  63. tests/test_query_parser.py +58 -0
  64. tests/test_templates_context.py +111 -0
  65. tests/test_utils.py +64 -64
  66. tests/utils/api.py +28 -0
  67. tests/utils/media.py +9 -0
  68. camomilla/serializers/fields/json.py +0 -49
  69. django_camomilla_cms-6.0.0b15.dist-info/RECORD +0 -105
  70. {django_camomilla_cms-6.0.0b15.dist-info → django_camomilla_cms-6.0.0b17.dist-info/licenses}/LICENSE +0 -0
  71. {django_camomilla_cms-6.0.0b15.dist-info → django_camomilla_cms-6.0.0b17.dist-info}/top_level.txt +0 -0
  72. {camomilla/contrib/rest_framework → tests/utils}/__init__.py +0 -0
@@ -0,0 +1,393 @@
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 example.website.models import TestModel
6
+
7
+
8
+ class ModelAPiRegisterTestCase(TestCase):
9
+ def setUp(self):
10
+ self.client = APIClient()
11
+ token = login_superuser()
12
+ self.client.credentials(HTTP_AUTHORIZATION='Token ' + token)
13
+
14
+
15
+ @pytest.mark.django_db
16
+ def test_model_api_register_access(self):
17
+ client = APIClient()
18
+ response = client.post("/api/models/test-model/")
19
+ assert response.status_code == 401
20
+
21
+
22
+ @pytest.mark.django_db
23
+ def test_model_api_register_crud(self):
24
+ # Create test model 1
25
+ response = self.client.post(
26
+ "/api/models/test-model/",
27
+ {
28
+ "title": "title_test_model_1"
29
+ },
30
+ format='json'
31
+ )
32
+ assert response.status_code == 201
33
+ assert len(TestModel.objects.all()) == 1
34
+ test_model = TestModel.objects.first()
35
+ assert test_model.id == 1
36
+ assert test_model.title == "title_test_model_1"
37
+
38
+ # Create test model 2
39
+ response = self.client.post(
40
+ "/api/models/test-model/",
41
+ {
42
+ "title": "title_test_model_2"
43
+ },
44
+ format='json'
45
+ )
46
+ assert response.status_code == 201
47
+ assert len(TestModel.objects.all()) == 2
48
+ test_model = TestModel.objects.last()
49
+ assert test_model.id == 2
50
+ assert test_model.title == "title_test_model_2"
51
+
52
+ # Update test model 2
53
+ response = self.client.patch(
54
+ "/api/models/test-model/2/",
55
+ {
56
+ "title": "title_test_model_2_updated",
57
+ },
58
+ format='json'
59
+ )
60
+ assert response.status_code == 200
61
+ assert len(TestModel.objects.all()) == 2
62
+ test_model = TestModel.objects.last()
63
+ assert test_model.id == 2
64
+ assert test_model.title == "title_test_model_2_updated"
65
+
66
+ # Read test model 2
67
+ response = self.client.get("/api/models/test-model/2/")
68
+ assert response.status_code == 200
69
+ assert response.json()['id'] == 2
70
+ assert response.json()['title'] == "title_test_model_2_updated"
71
+
72
+ # Read test models
73
+ response = self.client.get("/api/models/test-model/")
74
+ assert response.status_code == 200
75
+ assert response.json()[0]['id'] == 2
76
+ assert response.json()[0]['title'] == "title_test_model_2_updated"
77
+ assert response.json()[1]['id'] == 1
78
+ assert response.json()[1]['title'] == "title_test_model_1"
79
+
80
+ # Delete page
81
+ response = self.client.delete("/api/models/test-model/2/")
82
+ assert response.status_code == 204
83
+ assert len(TestModel.objects.all()) == 1
84
+ test_model = TestModel.objects.last()
85
+ assert test_model.id == 1
86
+ assert test_model.title == "title_test_model_1"
87
+
88
+
89
+ @pytest.mark.django_db
90
+ def test_model_api_register_listing(self):
91
+ # Create test model 1
92
+ response = self.client.post(
93
+ "/api/models/test-model/",
94
+ {
95
+ "title": "title_test_model_1"
96
+ },
97
+ format='json'
98
+ )
99
+ assert response.status_code == 201
100
+
101
+ # Create test model 2
102
+ response = self.client.post(
103
+ "/api/models/test-model/",
104
+ {
105
+ "title": "title_test_model_2"
106
+ },
107
+ format='json'
108
+ )
109
+ assert response.status_code == 201
110
+
111
+ # Create test model 3
112
+ response = self.client.post(
113
+ "/api/models/test-model/",
114
+ {
115
+ "title": "title_test_model_3"
116
+ },
117
+ format='json'
118
+ )
119
+ assert response.status_code == 201
120
+
121
+ # Simple Response
122
+ response = self.client.get("/api/models/test-model/")
123
+ assert response.status_code == 200
124
+ assert len(response.json()) == 3
125
+ assert response.json()[0]['id'] == 3
126
+ assert response.json()[1]['id'] == 2
127
+ assert response.json()[2]['id'] == 1
128
+
129
+ # Pagination
130
+ response = self.client.get("/api/models/test-model/?items=2")
131
+ assert response.status_code == 200
132
+ assert len(response.json()['items']) == 2
133
+ assert response.json()['items'][0]['id'] == 3
134
+ assert response.json()['items'][1]['id'] == 2
135
+ assert response.json()['paginator']['count'] == 3
136
+ assert response.json()['paginator']['page'] == 1
137
+ assert response.json()['paginator']['has_next'] == True
138
+ assert response.json()['paginator']['has_previous'] == False
139
+ assert response.json()['paginator']['pages'] == 2
140
+ assert response.json()['paginator']['page_size'] == 2
141
+
142
+ response = self.client.get("/api/models/test-model/?items=2&page=2")
143
+ assert response.status_code == 200
144
+ assert len(response.json()['items']) == 1
145
+ assert response.json()['items'][0]['id'] == 1
146
+ assert response.json()['paginator']['count'] == 3
147
+ assert response.json()['paginator']['page'] == 2
148
+ assert response.json()['paginator']['has_next'] == False
149
+ assert response.json()['paginator']['has_previous'] == True
150
+ assert response.json()['paginator']['pages'] == 2
151
+ assert response.json()['paginator']['page_size'] == 2
152
+
153
+ # Filtering
154
+ response = self.client.get("/api/models/test-model/?fltr=title=title_test_model_2")
155
+ assert response.status_code == 200
156
+ assert len(response.json()) == 1
157
+ assert response.json()[0]['id'] == 2
158
+ assert response.json()[0]['title'] == "title_test_model_2"
159
+
160
+ response = self.client.get("/api/models/test-model/?fltr=title=not_real_title")
161
+ assert response.status_code == 200
162
+ assert len(response.json()) == 0
163
+
164
+ response = self.client.get("/api/models/test-model/?fltr=title=title_test_model_2&fltr=id=2")
165
+ assert response.status_code == 200
166
+ assert len(response.json()) == 1
167
+ assert response.json()[0]['id'] == 2
168
+ assert response.json()[0]['title'] == "title_test_model_2"
169
+
170
+ response = self.client.get("/api/models/test-model/?fltr=title=title_test_model_2&fltr=id=3")
171
+ assert response.status_code == 200
172
+ assert len(response.json()) == 0
173
+
174
+ response = self.client.get("/api/models/test-model/?fltr=title__in=[title_test_model_2,title_test_model_3]")
175
+ assert response.status_code == 200
176
+ assert len(response.json()) == 2
177
+ assert response.json()[0]['id'] == 3
178
+ assert response.json()[0]['title'] == "title_test_model_3"
179
+ assert response.json()[1]['id'] == 2
180
+ assert response.json()[1]['title'] == "title_test_model_2"
181
+
182
+ response = self.client.get("/api/models/test-model/?fltr=title__in=[title_test_model_4,title_test_model_3]")
183
+ assert response.status_code == 200
184
+ assert len(response.json()) == 1
185
+ assert response.json()[0]['id'] == 3
186
+ assert response.json()[0]['title'] == "title_test_model_3"
187
+
188
+
189
+ @pytest.mark.django_db
190
+ def test_model_api_register_listing_filtered_model(self):
191
+ # Create filter argument register model 1
192
+ response = self.client.post(
193
+ "/api/models/filtered-register-model/",
194
+ {
195
+ "field_filtered": "test 1"
196
+ },
197
+ format='json'
198
+ )
199
+ assert response.status_code == 201
200
+
201
+ # Create filter argument register model 2
202
+ response = self.client.post(
203
+ "/api/models/filtered-register-model/",
204
+ {
205
+ "field_filtered": "pippo 2"
206
+ },
207
+ format='json'
208
+ )
209
+ assert response.status_code == 201
210
+
211
+ # Create filter argument register model 3
212
+ response = self.client.post(
213
+ "/api/models/filtered-register-model/",
214
+ {
215
+ "field_filtered": "3 test"
216
+ },
217
+ format='json'
218
+ )
219
+ assert response.status_code == 201
220
+
221
+ response = self.client.get("/api/models/filtered-register-model/")
222
+ assert response.status_code == 200
223
+ assert len(response.json()) == 2
224
+ assert response.json()[0]['id'] == 3
225
+ assert response.json()[0]['field_filtered'] == "3 test"
226
+ assert response.json()[1]['id'] == 1
227
+ assert response.json()[1]['field_filtered'] == "test 1"
228
+
229
+
230
+ @pytest.mark.django_db
231
+ def test_model_api_register_base_view_search(self):
232
+ # Verify search_fields = ["description"]
233
+ # Create custom arguments register model 1
234
+ response = self.client.post(
235
+ "/api/models/custom-base-arguments-register-model/",
236
+ {
237
+ "description": "description_1"
238
+ },
239
+ format='json'
240
+ )
241
+ assert response.status_code == 201
242
+
243
+ # Create custom arguments register model 2
244
+ response = self.client.post(
245
+ "/api/models/custom-base-arguments-register-model/",
246
+ {
247
+ "description": "description_2"
248
+ },
249
+ format='json'
250
+ )
251
+ assert response.status_code == 201
252
+
253
+ # Create custom arguments register model 3
254
+ response = self.client.post(
255
+ "/api/models/custom-base-arguments-register-model/",
256
+ {
257
+ "description": "description_3"
258
+ },
259
+ format='json'
260
+ )
261
+ assert response.status_code == 201
262
+
263
+ response = self.client.get("/api/models/custom-base-arguments-register-model/?search=not_real_description")
264
+ assert response.status_code == 200
265
+ assert len(response.json()) == 0
266
+
267
+ response = self.client.get("/api/models/custom-base-arguments-register-model/?search=description_1")
268
+ assert response.status_code == 200
269
+ assert len(response.json()) == 1
270
+ assert response.json()[0]['id'] == 1
271
+ assert response.json()[0]['description'] == "description_1"
272
+
273
+
274
+ @pytest.mark.django_db
275
+ def test_model_api_register_base_serializer_search(self):
276
+ # Verify description = BaseModelSerializer.CharField(min_length=3)
277
+ # Create custom arguments register model 1
278
+ response = self.client.post(
279
+ "/api/models/custom-base-arguments-register-model/",
280
+ {
281
+ "description": "12"
282
+ },
283
+ format='json'
284
+ )
285
+ assert response.status_code == 400
286
+
287
+ # Create custom arguments register model 2
288
+ response = self.client.post(
289
+ "/api/models/custom-base-arguments-register-model/",
290
+ {
291
+ "description": "1234"
292
+ },
293
+ format='json'
294
+ )
295
+ assert response.status_code == 201
296
+
297
+ @pytest.mark.django_db
298
+ def test_model_api_register_view_search(self):
299
+ # Verify {"search_fields": ["name"]}
300
+ # Create custom arguments register model 1
301
+ response = self.client.post(
302
+ "/api/models/custom-arguments-register-model/",
303
+ {
304
+ "name": "name_1"
305
+ },
306
+ format='json'
307
+ )
308
+ assert response.status_code == 201
309
+
310
+ # Create custom arguments register model 2
311
+ response = self.client.post(
312
+ "/api/models/custom-arguments-register-model/",
313
+ {
314
+ "name": "name_2"
315
+ },
316
+ format='json'
317
+ )
318
+ assert response.status_code == 201
319
+
320
+ # Create custom arguments register model 3
321
+ response = self.client.post(
322
+ "/api/models/custom-arguments-register-model/",
323
+ {
324
+ "name": "name_3"
325
+ },
326
+ format='json'
327
+ )
328
+ assert response.status_code == 201
329
+
330
+ response = self.client.get("/api/models/custom-arguments-register-model/?search=not_real_name")
331
+ assert response.status_code == 200
332
+ assert len(response.json()) == 0
333
+
334
+ response = self.client.get("/api/models/custom-arguments-register-model/?search=name_1")
335
+ assert response.status_code == 200
336
+ assert len(response.json()) == 1
337
+ assert response.json()[0]['name'] == "name_1"
338
+
339
+ @pytest.mark.django_db
340
+ def test_model_api_register_serializer_search(self):
341
+ # Verify {"fields": ["name"]}
342
+ # Create custom arguments register model
343
+ response = self.client.post(
344
+ "/api/models/custom-arguments-register-model/",
345
+ {
346
+ "name": "1234"
347
+ },
348
+ format='json'
349
+ )
350
+ assert response.status_code == 201
351
+ assert 'id' not in response.json()
352
+ assert response.json()['name'] == "1234"
353
+
354
+ @pytest.mark.django_db
355
+ def test_model_api_register_listing_filtered_model(self):
356
+ # Verify filters={"field_filtered__icontains": "test"}
357
+ # Create filter argument register model 1
358
+ response = self.client.post(
359
+ "/api/models/filtered-register-model/",
360
+ {
361
+ "field_filtered": "test 1"
362
+ },
363
+ format='json'
364
+ )
365
+ assert response.status_code == 201
366
+
367
+ # Create filter argument register model 2
368
+ response = self.client.post(
369
+ "/api/models/filtered-register-model/",
370
+ {
371
+ "field_filtered": "pippo 2"
372
+ },
373
+ format='json'
374
+ )
375
+ assert response.status_code == 201
376
+
377
+ # Create filter argument register model 3
378
+ response = self.client.post(
379
+ "/api/models/filtered-register-model/",
380
+ {
381
+ "field_filtered": "3 test"
382
+ },
383
+ format='json'
384
+ )
385
+ assert response.status_code == 201
386
+
387
+ response = self.client.get("/api/models/filtered-register-model/")
388
+ assert response.status_code == 200
389
+ assert len(response.json()) == 2
390
+ assert response.json()[0]['id'] == 3
391
+ assert response.json()[0]['field_filtered'] == "3 test"
392
+ assert response.json()[1]['id'] == 1
393
+ assert response.json()[1]['field_filtered'] == "test 1"