django-camomilla-cms 6.1.4__tar.gz → 6.2.1__tar.gz
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.
- {django_camomilla_cms-6.1.4/django_camomilla_cms.egg-info → django_camomilla_cms-6.2.1}/PKG-INFO +2 -2
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/camomilla/__init__.py +1 -1
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/camomilla/managers/pages.py +36 -5
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/camomilla/models/mixins/__init__.py +1 -0
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/camomilla/models/page.py +3 -2
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/camomilla/serializers/mixins/translation.py +2 -3
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/camomilla/serializers/user.py +4 -0
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/camomilla/settings.py +12 -1
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/camomilla/templates/defaults/base.html +2 -0
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/camomilla/templates/defaults/parts/langswitch.html +7 -0
- django_camomilla_cms-6.2.1/camomilla/theme/__init__.py +1 -0
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/camomilla/theme/admin/pages.py +1 -1
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/camomilla/translation.py +1 -0
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/camomilla/utils/translation.py +7 -8
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/camomilla/views/articles.py +0 -2
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/camomilla/views/contents.py +0 -2
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/camomilla/views/decorators.py +23 -3
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/camomilla/views/medias.py +0 -3
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/camomilla/views/menus.py +0 -2
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/camomilla/views/pages.py +10 -5
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/camomilla/views/tags.py +0 -2
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/camomilla/views/users.py +1 -2
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1/django_camomilla_cms.egg-info}/PKG-INFO +2 -2
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/django_camomilla_cms.egg-info/SOURCES.txt +5 -0
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/django_camomilla_cms.egg-info/requires.txt +1 -1
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/pyproject.toml +8 -1
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/setup.py +1 -1
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/tests/test_admin_page_form.py +2 -2
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/tests/test_camomilla_filters.py +1 -1
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/tests/test_model_api_permissions.py +6 -0
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/tests/test_pages.py +18 -0
- django_camomilla_cms-6.2.1/tests/test_parsers.py +62 -0
- django_camomilla_cms-6.2.1/tests/test_sitemap.py +16 -0
- django_camomilla_cms-6.2.1/tests/test_utils_getters.py +41 -0
- django_camomilla_cms-6.2.1/tests/test_utils_normalization.py +37 -0
- django_camomilla_cms-6.2.1/tests/test_utils_setters.py +62 -0
- django_camomilla_cms-6.1.4/camomilla/theme/__init__.py +0 -1
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/LICENSE +0 -0
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/MANIFEST.in +0 -0
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/README.md +0 -0
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/camomilla/apps.py +0 -0
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/camomilla/authentication.py +0 -0
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/camomilla/context_processors.py +0 -0
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/camomilla/contrib/__init__.py +0 -0
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/camomilla/contrib/modeltranslation/__init__.py +0 -0
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/camomilla/contrib/modeltranslation/hvad_migration.py +0 -0
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/camomilla/defaults.py +0 -0
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/camomilla/dynamic_pages_urls.py +0 -0
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/camomilla/exceptions.py +0 -0
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/camomilla/fields/__init__.py +0 -0
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/camomilla/fields/json.py +0 -0
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/camomilla/management/__init__.py +0 -0
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/camomilla/management/commands/__init__.py +0 -0
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/camomilla/management/commands/regenerate_thumbnails.py +0 -0
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/camomilla/managers/__init__.py +0 -0
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/camomilla/model_api.py +0 -0
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/camomilla/models/__init__.py +0 -0
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/camomilla/models/article.py +0 -0
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/camomilla/models/content.py +0 -0
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/camomilla/models/media.py +0 -0
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/camomilla/models/menu.py +0 -0
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/camomilla/openapi/__init__.py +0 -0
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/camomilla/openapi/schema.py +0 -0
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/camomilla/parsers.py +0 -0
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/camomilla/permissions.py +0 -0
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/camomilla/redirects.py +0 -0
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/camomilla/serializers/__init__.py +0 -0
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/camomilla/serializers/article.py +0 -0
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/camomilla/serializers/base/__init__.py +0 -0
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/camomilla/serializers/content_type.py +0 -0
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/camomilla/serializers/fields/__init__.py +0 -0
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/camomilla/serializers/fields/file.py +0 -0
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/camomilla/serializers/fields/related.py +0 -0
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/camomilla/serializers/media.py +0 -0
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/camomilla/serializers/menu.py +0 -0
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/camomilla/serializers/mixins/__init__.py +0 -0
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/camomilla/serializers/mixins/fields.py +0 -0
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/camomilla/serializers/mixins/filter_fields.py +0 -0
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/camomilla/serializers/mixins/json.py +0 -0
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/camomilla/serializers/mixins/language.py +0 -0
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/camomilla/serializers/mixins/nesting.py +0 -0
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/camomilla/serializers/mixins/optimize.py +0 -0
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/camomilla/serializers/mixins/ordering.py +0 -0
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/camomilla/serializers/mixins/page.py +0 -0
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/camomilla/serializers/page.py +0 -0
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/camomilla/serializers/utils.py +0 -0
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/camomilla/serializers/validators.py +0 -0
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/camomilla/sitemap.py +0 -0
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/camomilla/storages/__init__.py +0 -0
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/camomilla/storages/default.py +0 -0
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/camomilla/storages/optimize.py +0 -0
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/camomilla/storages/overwrite.py +0 -0
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/camomilla/templates/admin/camomilla/page/change_form.html +0 -0
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/camomilla/templates/defaults/articles/default.html +0 -0
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/camomilla/templates/defaults/pages/default.html +0 -0
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/camomilla/templates/defaults/parts/menu.html +0 -0
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/camomilla/templates/defaults/widgets/media_select_multiple.html +0 -0
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/camomilla/templates_context/__init__.py +0 -0
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/camomilla/templates_context/autodiscover.py +0 -0
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/camomilla/templates_context/rendering.py +0 -0
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/camomilla/templatetags/__init__.py +0 -0
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/camomilla/templatetags/camomilla_filters.py +0 -0
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/camomilla/templatetags/menus.py +0 -0
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/camomilla/templatetags/model_extras.py +0 -0
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/camomilla/theme/admin/__init__.py +0 -0
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/camomilla/theme/admin/translations.py +0 -0
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/camomilla/theme/apps.py +0 -0
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/camomilla/theme/static/admin/css/responsive.css +0 -0
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/camomilla/theme/static/admin/img/favicon.ico +0 -0
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/camomilla/theme/static/admin/img/logo.svg +0 -0
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/camomilla/theme/templates/admin/base.html +0 -0
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/camomilla/theme/templates/rosetta/base.html +0 -0
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/camomilla/urls.py +0 -0
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/camomilla/utils/__init__.py +0 -0
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/camomilla/utils/getters.py +0 -0
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/camomilla/utils/normalization.py +0 -0
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/camomilla/utils/query_parser.py +0 -0
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/camomilla/utils/seo.py +0 -0
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/camomilla/utils/setters.py +0 -0
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/camomilla/utils/templates.py +0 -0
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/camomilla/views/__init__.py +0 -0
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/camomilla/views/base/__init__.py +0 -0
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/camomilla/views/languages.py +0 -0
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/camomilla/views/mixins/__init__.py +0 -0
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/camomilla/views/mixins/bulk_actions.py +0 -0
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/camomilla/views/mixins/language.py +0 -0
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/camomilla/views/mixins/optimize.py +0 -0
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/camomilla/views/mixins/ordering.py +0 -0
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/camomilla/views/mixins/pagination.py +0 -0
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/camomilla/views/mixins/permissions.py +0 -0
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/django_camomilla_cms.egg-info/dependency_links.txt +0 -0
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/django_camomilla_cms.egg-info/top_level.txt +0 -0
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/setup.cfg +0 -0
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/tests/__init__.py +0 -0
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/tests/fixtures/__init__.py +0 -0
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/tests/test_api.py +0 -0
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/tests/test_media.py +0 -0
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/tests/test_menu.py +0 -0
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/tests/test_model_api.py +0 -0
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/tests/test_model_api_register.py +0 -0
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/tests/test_models.py +0 -0
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/tests/test_page_meta.py +0 -0
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/tests/test_page_relation_api.py +0 -0
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/tests/test_query_parser.py +0 -0
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/tests/test_templates_context.py +0 -0
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/tests/test_utils.py +0 -0
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/tests/utils/__init__.py +0 -0
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/tests/utils/api.py +0 -0
- {django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/tests/utils/media.py +0 -0
{django_camomilla_cms-6.1.4/django_camomilla_cms.egg-info → django_camomilla_cms-6.2.1}/PKG-INFO
RENAMED
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: django-camomilla-cms
|
3
|
-
Version: 6.1
|
3
|
+
Version: 6.2.1
|
4
4
|
Summary: Django powered cms
|
5
5
|
Author-email: Lotrèk <dimmitutto@lotrek.it>
|
6
6
|
License: MIT
|
@@ -17,7 +17,7 @@ License-File: LICENSE
|
|
17
17
|
Requires-Dist: django-modeltranslation<=0.18.12,>=0.18.7
|
18
18
|
Requires-Dist: djsuperadmin<1.0.0,>=0.9
|
19
19
|
Requires-Dist: djangorestframework<=3.14.0,>=3.10.0
|
20
|
-
Requires-Dist: django-structured-json-field>=1.1.
|
20
|
+
Requires-Dist: django-structured-json-field>=1.1.2
|
21
21
|
Requires-Dist: Pillow>=10.0.0
|
22
22
|
Requires-Dist: django-admin-interface<1.0.0,>=0.26.0
|
23
23
|
Requires-Dist: django-ckeditor<7.0.0,>=5.7.1
|
@@ -42,13 +42,44 @@ class PageQuerySet(QuerySet):
|
|
42
42
|
|
43
43
|
|
44
44
|
class UrlNodeManager(models.Manager):
|
45
|
+
|
46
|
+
def get_reverse_pages_relations(self):
|
47
|
+
"""
|
48
|
+
Get all reverse relations coming from AbstractPages models.
|
49
|
+
This is used to annotate the UrlNode with the related page fields.
|
50
|
+
"""
|
51
|
+
from camomilla.models.page import AbstractPage
|
52
|
+
|
53
|
+
relations = []
|
54
|
+
|
55
|
+
for field in self.model._meta.get_fields():
|
56
|
+
if not (hasattr(field, "related_model") and field.one_to_one):
|
57
|
+
continue
|
58
|
+
|
59
|
+
if not issubclass(field.related_model, AbstractPage):
|
60
|
+
continue
|
61
|
+
|
62
|
+
if field.remote_field.name != "url_node":
|
63
|
+
continue
|
64
|
+
|
65
|
+
related_name = field.get_accessor_name()
|
66
|
+
relations.append(
|
67
|
+
{
|
68
|
+
"name": related_name,
|
69
|
+
"model": field.related_model,
|
70
|
+
"field_name": field.remote_field.name,
|
71
|
+
"field": field,
|
72
|
+
}
|
73
|
+
)
|
74
|
+
return relations
|
75
|
+
|
45
76
|
@property
|
46
77
|
def related_names(self):
|
47
|
-
self._related_names = getattr(
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
78
|
+
self._related_names = getattr(self, "_related_names", None)
|
79
|
+
if self._related_names is None:
|
80
|
+
self._related_names = list(
|
81
|
+
set([rel["name"] for rel in self.get_reverse_pages_relations()])
|
82
|
+
)
|
52
83
|
return self._related_names
|
53
84
|
|
54
85
|
def _annotate_fields(
|
@@ -99,7 +99,7 @@ class UrlNode(models.Model):
|
|
99
99
|
LANG_PERMALINK_FIELDS = (
|
100
100
|
[
|
101
101
|
build_localized_fieldname("permalink", lang)
|
102
|
-
for lang in settings.
|
102
|
+
for lang in settings.LANGUAGE_CODES
|
103
103
|
]
|
104
104
|
if settings.ENABLE_TRANSLATIONS
|
105
105
|
else ["permalink"]
|
@@ -319,7 +319,7 @@ class AbstractPage(SeoMixin, MetaMixin, models.Model, metaclass=PageBase):
|
|
319
319
|
@property
|
320
320
|
def breadcrumbs(self) -> Sequence[dict]:
|
321
321
|
breadcrumb = {
|
322
|
-
"permalink": self.
|
322
|
+
"permalink": self.routerlink,
|
323
323
|
"title": self.breadcrumbs_title or self.title or "",
|
324
324
|
}
|
325
325
|
if self.parent:
|
@@ -481,6 +481,7 @@ class AbstractPage(SeoMixin, MetaMixin, models.Model, metaclass=PageBase):
|
|
481
481
|
)
|
482
482
|
if preview:
|
483
483
|
permalinks = {k: f"{v}?preview=true" for k, v in permalinks.items()}
|
484
|
+
permalinks.pop(get_language(), None)
|
484
485
|
return permalinks
|
485
486
|
|
486
487
|
class Meta:
|
@@ -1,6 +1,5 @@
|
|
1
1
|
from functools import cached_property
|
2
2
|
from typing import Iterable, List
|
3
|
-
from modeltranslation import settings as mt_settings
|
4
3
|
from modeltranslation.translator import NotRegistered, translator
|
5
4
|
from modeltranslation.utils import build_localized_fieldname
|
6
5
|
from rest_framework import serializers
|
@@ -8,7 +7,7 @@ from rest_framework.exceptions import ValidationError
|
|
8
7
|
from camomilla.utils.getters import pointed_getter
|
9
8
|
from camomilla.utils.translation import is_translatable
|
10
9
|
from camomilla.utils.translation import nest_to_plain, plain_to_nest
|
11
|
-
from camomilla.settings import API_TRANSLATION_ACCESSOR
|
10
|
+
from camomilla.settings import API_TRANSLATION_ACCESSOR, LANGUAGE_CODES
|
12
11
|
|
13
12
|
|
14
13
|
class TranslationsMixin(serializers.ModelSerializer):
|
@@ -94,7 +93,7 @@ class RemoveTranslationsMixin(serializers.ModelSerializer):
|
|
94
93
|
included_translations = []
|
95
94
|
|
96
95
|
field_names = super().get_default_field_names(declared_fields, model_info)
|
97
|
-
for lang in
|
96
|
+
for lang in LANGUAGE_CODES:
|
98
97
|
if lang not in included_translations:
|
99
98
|
for field in self.translation_fields:
|
100
99
|
localized_fieldname = build_localized_fieldname(field, lang)
|
@@ -105,6 +105,10 @@ INTEGRATIONS_ASTRO_URL = pointed_getter(
|
|
105
105
|
django_settings, "CAMOMILLA.INTEGRATIONS.ASTRO.URL", ""
|
106
106
|
)
|
107
107
|
|
108
|
+
PAGE_ROUTER_CACHE = pointed_getter(
|
109
|
+
django_settings, "CAMOMILLA.API.PAGES.ROUTER_CACHE", 60 * 15
|
110
|
+
)
|
111
|
+
|
108
112
|
DEBUG = pointed_getter(django_settings, "CAMOMILLA.DEBUG", django_settings.DEBUG)
|
109
113
|
|
110
114
|
# camomilla settings example
|
@@ -133,6 +137,13 @@ DEBUG = pointed_getter(django_settings, "CAMOMILLA.DEBUG", django_settings.DEBUG
|
|
133
137
|
# "URL": "http://localhost:4321"
|
134
138
|
# }
|
135
139
|
# }
|
136
|
-
# "API": {
|
140
|
+
# "API": {
|
141
|
+
# "NESTING_DEPTH": 10,
|
142
|
+
# "TRANSLATION_ACCESSOR": "translations",
|
143
|
+
# "PAGES": {
|
144
|
+
# "DEFAULT_SERIALIZER": "camomilla.serializers.page.RouteSerializer"
|
145
|
+
# },
|
146
|
+
# "ROUTER_CACHE": 60 * 15
|
147
|
+
# },
|
137
148
|
# "DEBUG": False
|
138
149
|
# }
|
@@ -36,6 +36,13 @@
|
|
36
36
|
{% get_language_info_list for LANGUAGES as languages %}
|
37
37
|
{% get_language_info for LANGUAGE_CODE as current_lang %}
|
38
38
|
|
39
|
+
<div class="language-switch--btn" data-lang="{{current_lang.code}}"
|
40
|
+
{% if current_lang.code != LANGUAGE_CODE %}
|
41
|
+
onclick="submitLanguageWithoutRedirect('{{current_lang.code}}');"
|
42
|
+
{% endif %}
|
43
|
+
>
|
44
|
+
<a>{{ current_lang.name_translated }} {% if current_lang.code == LANGUAGE_CODE %} 👾 {% endif %}</a>
|
45
|
+
</div>
|
39
46
|
{% for lang_code, redirect in page.alternate_urls.items %}
|
40
47
|
<div class="language-switch--btn" data-lang="{{lang_code}}"
|
41
48
|
{% if current_lang.code != lang_code %}
|
@@ -0,0 +1 @@
|
|
1
|
+
__version__ = "6.2.1"
|
@@ -29,7 +29,7 @@ class AbstractPageModelForm(
|
|
29
29
|
super().__init__(*args, **kwargs)
|
30
30
|
templates = [(t, t) for t in get_templates(request)]
|
31
31
|
templates.insert(0, ("", "---------"))
|
32
|
-
self.fields["template"] = forms.ChoiceField(choices=templates)
|
32
|
+
self.fields["template"] = forms.ChoiceField(choices=templates, required=False)
|
33
33
|
|
34
34
|
def get_initial_for_field(self, field, field_name):
|
35
35
|
if field_name in UrlNode.LANG_PERMALINK_FIELDS:
|
@@ -3,13 +3,12 @@ from typing import Any, Sequence, Iterator, Union, List
|
|
3
3
|
|
4
4
|
from django.db.models import Model, Q
|
5
5
|
from django.utils.translation.trans_real import activate, get_language
|
6
|
-
from modeltranslation.settings import AVAILABLE_LANGUAGES, DEFAULT_LANGUAGE
|
7
6
|
from modeltranslation.utils import build_localized_fieldname
|
8
|
-
from camomilla.settings import BASE_URL
|
7
|
+
from camomilla.settings import BASE_URL, DEFAULT_LANGUAGE, LANGUAGE_CODES
|
9
8
|
from django.http import QueryDict
|
10
9
|
|
11
10
|
|
12
|
-
def activate_languages(languages: Sequence[str] =
|
11
|
+
def activate_languages(languages: Sequence[str] = LANGUAGE_CODES) -> Iterator[str]:
|
13
12
|
old = get_language()
|
14
13
|
for language in languages:
|
15
14
|
activate(language)
|
@@ -37,7 +36,7 @@ def url_lang_decompose(url):
|
|
37
36
|
if BASE_URL and url.startswith(BASE_URL):
|
38
37
|
url = url[len(BASE_URL) :]
|
39
38
|
data = {"url": url, "permalink": url, "language": DEFAULT_LANGUAGE}
|
40
|
-
result = re.match(rf"^/?({'|'.join(
|
39
|
+
result = re.match(rf"^/?({'|'.join(LANGUAGE_CODES)})?/(.*)", url) # noqa: W605
|
41
40
|
groups = result and result.groups()
|
42
41
|
if groups and len(groups) == 2:
|
43
42
|
data["language"] = groups[0]
|
@@ -48,14 +47,14 @@ def url_lang_decompose(url):
|
|
48
47
|
def get_field_translations(instance: Model, field_name: str, *args, **kwargs):
|
49
48
|
return {
|
50
49
|
lang: get_nofallbacks(instance, field_name, language=lang, *args, **kwargs)
|
51
|
-
for lang in
|
50
|
+
for lang in LANGUAGE_CODES
|
52
51
|
}
|
53
52
|
|
54
53
|
|
55
54
|
def lang_fallback_query(**kwargs):
|
56
55
|
current_lang = get_language()
|
57
56
|
query = Q()
|
58
|
-
for lang in
|
57
|
+
for lang in LANGUAGE_CODES:
|
59
58
|
query |= Q(**{f"{key}_{lang}": value for key, value in kwargs.items()})
|
60
59
|
if current_lang:
|
61
60
|
query = query & Q(
|
@@ -77,7 +76,7 @@ def plain_to_nest(data, fields, accessor="translations"):
|
|
77
76
|
into a dictionary with nested translations fields (es. {"translations": {"en": {"title": "Hello"}}}).
|
78
77
|
"""
|
79
78
|
trans_data = {}
|
80
|
-
for lang in
|
79
|
+
for lang in LANGUAGE_CODES:
|
81
80
|
lang_data = {}
|
82
81
|
for field in fields:
|
83
82
|
trans_field_name = build_localized_fieldname(field, lang)
|
@@ -101,7 +100,7 @@ def nest_to_plain(
|
|
101
100
|
if isinstance(data, QueryDict):
|
102
101
|
data = data.dict()
|
103
102
|
translations = data.pop(accessor, {})
|
104
|
-
for lang in
|
103
|
+
for lang in LANGUAGE_CODES:
|
105
104
|
nest_trans = translations.pop(lang, {})
|
106
105
|
for k in fields:
|
107
106
|
data.pop(k, None) # this removes all trans field without lang
|
@@ -1,5 +1,4 @@
|
|
1
1
|
from camomilla.models import Article
|
2
|
-
from camomilla.permissions import CamomillaBasePermissions
|
3
2
|
from camomilla.serializers import ArticleSerializer
|
4
3
|
from camomilla.views.base import BaseModelViewset
|
5
4
|
from camomilla.views.mixins import BulkDeleteMixin, GetUserLanguageMixin
|
@@ -8,6 +7,5 @@ from camomilla.views.mixins import BulkDeleteMixin, GetUserLanguageMixin
|
|
8
7
|
class ArticleViewSet(GetUserLanguageMixin, BulkDeleteMixin, BaseModelViewset):
|
9
8
|
queryset = Article.objects.all()
|
10
9
|
serializer_class = ArticleSerializer
|
11
|
-
permission_classes = (CamomillaBasePermissions,)
|
12
10
|
search_fields = ["title", "identifier", "content", "permalink"]
|
13
11
|
model = Article
|
@@ -4,7 +4,6 @@ from django.http import JsonResponse
|
|
4
4
|
from rest_framework.decorators import action
|
5
5
|
|
6
6
|
from camomilla.models import Content
|
7
|
-
from camomilla.permissions import CamomillaBasePermissions
|
8
7
|
from camomilla.serializers import ContentSerializer
|
9
8
|
from camomilla.views.base import BaseModelViewset
|
10
9
|
from camomilla.views.mixins import BulkDeleteMixin, GetUserLanguageMixin
|
@@ -14,7 +13,6 @@ class ContentViewSet(GetUserLanguageMixin, BulkDeleteMixin, BaseModelViewset):
|
|
14
13
|
queryset = Content.objects.all()
|
15
14
|
serializer_class = ContentSerializer
|
16
15
|
model = Content
|
17
|
-
permission_classes = (CamomillaBasePermissions,)
|
18
16
|
|
19
17
|
@action(detail=True, methods=["get", "patch"])
|
20
18
|
def djsuperadmin(self, request, pk):
|
@@ -1,6 +1,7 @@
|
|
1
1
|
import functools
|
2
2
|
from django.utils.translation import activate
|
3
|
-
from django.
|
3
|
+
from django.views.decorators.cache import cache_page
|
4
|
+
from camomilla.settings import LANGUAGE_CODES, DEFAULT_LANGUAGE
|
4
5
|
|
5
6
|
|
6
7
|
def active_lang(*args, **kwargs):
|
@@ -11,12 +12,12 @@ def active_lang(*args, **kwargs):
|
|
11
12
|
request = args[0].request
|
12
13
|
else:
|
13
14
|
request = args[0] if len(args) else kwargs.get("request", None)
|
14
|
-
lang =
|
15
|
+
lang = DEFAULT_LANGUAGE
|
15
16
|
if request and hasattr(request, "GET"):
|
16
17
|
lang = request.GET.get("lang", request.GET.get("language", lang))
|
17
18
|
if request and hasattr(request, "data"):
|
18
19
|
lang = request.data.pop("lang", request.data.pop("language", lang))
|
19
|
-
if lang and lang in
|
20
|
+
if lang and lang in LANGUAGE_CODES:
|
20
21
|
activate(lang)
|
21
22
|
request.LANGUAGE_CODE = lang
|
22
23
|
return func(*args, **kwargs)
|
@@ -24,3 +25,22 @@ def active_lang(*args, **kwargs):
|
|
24
25
|
return wrapped_func
|
25
26
|
|
26
27
|
return decorator
|
28
|
+
|
29
|
+
|
30
|
+
def staff_excluded_cache(timing=None):
|
31
|
+
def decorator(func):
|
32
|
+
if timing is None:
|
33
|
+
return func # No caching applied
|
34
|
+
|
35
|
+
@functools.wraps(func)
|
36
|
+
def wrapped_func(*args, **kwargs):
|
37
|
+
request = args[0] if len(args) else kwargs.get("request", None)
|
38
|
+
if request and hasattr(request, "user"):
|
39
|
+
user = request.user
|
40
|
+
if user.is_authenticated and user.is_staff:
|
41
|
+
return func(*args, **kwargs)
|
42
|
+
return cache_page(timing)(func)(*args, **kwargs)
|
43
|
+
|
44
|
+
return wrapped_func
|
45
|
+
|
46
|
+
return decorator
|
@@ -3,7 +3,6 @@ from rest_framework.response import Response
|
|
3
3
|
|
4
4
|
from camomilla.models import Media, MediaFolder
|
5
5
|
from camomilla.parsers import MultipartJsonParser
|
6
|
-
from camomilla.permissions import CamomillaBasePermissions
|
7
6
|
from camomilla.serializers import (
|
8
7
|
MediaFolderSerializer,
|
9
8
|
MediaListSerializer,
|
@@ -33,7 +32,6 @@ class MediaFolderViewSet(
|
|
33
32
|
):
|
34
33
|
model = MediaFolder
|
35
34
|
serializer_class = MediaFolderSerializer
|
36
|
-
permission_classes = (CamomillaBasePermissions,)
|
37
35
|
items_per_page = 18
|
38
36
|
search_fields = ["title", "alt_text", "file"]
|
39
37
|
|
@@ -85,6 +83,5 @@ class MediaViewSet(
|
|
85
83
|
):
|
86
84
|
queryset = Media.objects.all()
|
87
85
|
serializer_class = MediaSerializer
|
88
|
-
permission_classes = (CamomillaBasePermissions,)
|
89
86
|
model = Media
|
90
87
|
parser_classes = [MultipartJsonParser, JSONParser]
|
@@ -7,7 +7,6 @@ from rest_framework.response import Response
|
|
7
7
|
|
8
8
|
from camomilla.models import AbstractPage, Menu
|
9
9
|
from camomilla.models.page import UrlNode
|
10
|
-
from camomilla.permissions import CamomillaBasePermissions
|
11
10
|
from camomilla.serializers import ContentTypeSerializer, MenuSerializer
|
12
11
|
from camomilla.serializers.page import UrlNodeSerializer
|
13
12
|
from camomilla.views.base import BaseModelViewset
|
@@ -17,7 +16,6 @@ from camomilla.views.decorators import active_lang
|
|
17
16
|
class MenuViewSet(BaseModelViewset):
|
18
17
|
queryset = Menu.objects.all()
|
19
18
|
serializer_class = MenuSerializer
|
20
|
-
permission_classes = (CamomillaBasePermissions,)
|
21
19
|
model = Menu
|
22
20
|
|
23
21
|
lookup_field = "key"
|
@@ -1,26 +1,27 @@
|
|
1
1
|
from camomilla.models import Page
|
2
2
|
from camomilla.models.page import UrlNode, UrlRedirect
|
3
|
-
from camomilla.permissions import CamomillaBasePermissions
|
4
3
|
from camomilla.serializers import PageSerializer
|
5
4
|
from camomilla.serializers.page import RouteSerializer
|
5
|
+
from camomilla.utils.translation import url_lang_decompose
|
6
6
|
from camomilla.views.base import BaseModelViewset
|
7
|
-
from camomilla.views.decorators import
|
7
|
+
from camomilla.views.decorators import staff_excluded_cache
|
8
8
|
from camomilla.views.mixins import BulkDeleteMixin, GetUserLanguageMixin
|
9
9
|
from rest_framework.decorators import api_view, permission_classes
|
10
10
|
from rest_framework.response import Response
|
11
11
|
from rest_framework import permissions
|
12
|
+
from django.utils.translation.trans_real import activate as activate_language
|
12
13
|
from django.shortcuts import get_object_or_404
|
14
|
+
from camomilla.settings import PAGE_ROUTER_CACHE
|
13
15
|
|
14
16
|
|
15
17
|
class PageViewSet(GetUserLanguageMixin, BulkDeleteMixin, BaseModelViewset):
|
16
18
|
queryset = Page.objects.all()
|
17
19
|
serializer_class = PageSerializer
|
18
|
-
permission_classes = (CamomillaBasePermissions,)
|
19
20
|
model = Page
|
20
21
|
|
21
22
|
|
22
|
-
@active_lang()
|
23
23
|
@api_view(["GET"])
|
24
|
+
@staff_excluded_cache(PAGE_ROUTER_CACHE)
|
24
25
|
@permission_classes(
|
25
26
|
[
|
26
27
|
permissions.AllowAny,
|
@@ -31,5 +32,9 @@ def pages_router(request, permalink=""):
|
|
31
32
|
if redirect:
|
32
33
|
redirect = redirect.redirect()
|
33
34
|
return Response({"redirect": redirect.url, "status": redirect.status_code})
|
34
|
-
|
35
|
+
url_decomposition = url_lang_decompose(permalink)
|
36
|
+
if not url_decomposition["permalink"].startswith("/"):
|
37
|
+
url_decomposition["permalink"] = f"/{url_decomposition['permalink']}"
|
38
|
+
activate_language(url_decomposition["language"])
|
39
|
+
node: UrlNode = get_object_or_404(UrlNode, permalink=url_decomposition["permalink"])
|
35
40
|
return Response(RouteSerializer(node, context={"request": request}).data)
|
@@ -1,5 +1,4 @@
|
|
1
1
|
from camomilla.models import Tag
|
2
|
-
from camomilla.permissions import CamomillaBasePermissions
|
3
2
|
from camomilla.serializers import TagSerializer
|
4
3
|
from camomilla.views.base import BaseModelViewset
|
5
4
|
from camomilla.views.mixins import BulkDeleteMixin, GetUserLanguageMixin
|
@@ -8,5 +7,4 @@ from camomilla.views.mixins import BulkDeleteMixin, GetUserLanguageMixin
|
|
8
7
|
class TagViewSet(GetUserLanguageMixin, BulkDeleteMixin, BaseModelViewset):
|
9
8
|
queryset = Tag.objects.all()
|
10
9
|
serializer_class = TagSerializer
|
11
|
-
permission_classes = (CamomillaBasePermissions,)
|
12
10
|
model = Tag
|
@@ -8,7 +8,7 @@ from rest_framework.permissions import IsAuthenticated
|
|
8
8
|
from rest_framework.response import Response
|
9
9
|
from rest_framework.views import APIView
|
10
10
|
|
11
|
-
from camomilla.permissions import
|
11
|
+
from camomilla.permissions import CamomillaSuperUser, ReadOnly
|
12
12
|
from camomilla.serializers import (
|
13
13
|
PermissionSerializer,
|
14
14
|
UserProfileSerializer,
|
@@ -30,7 +30,6 @@ class UserViewSet(BaseModelViewset):
|
|
30
30
|
queryset = get_user_model().objects.all()
|
31
31
|
serializer_class = UserSerializer
|
32
32
|
model = get_user_model()
|
33
|
-
permission_classes = (CamomillaSuperUser | CamomillaBasePermissions,)
|
34
33
|
|
35
34
|
@action(detail=False, methods=["get", "put"], permission_classes=(IsAuthenticated,))
|
36
35
|
def current(self, request):
|
{django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1/django_camomilla_cms.egg-info}/PKG-INFO
RENAMED
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: django-camomilla-cms
|
3
|
-
Version: 6.1
|
3
|
+
Version: 6.2.1
|
4
4
|
Summary: Django powered cms
|
5
5
|
Author-email: Lotrèk <dimmitutto@lotrek.it>
|
6
6
|
License: MIT
|
@@ -17,7 +17,7 @@ License-File: LICENSE
|
|
17
17
|
Requires-Dist: django-modeltranslation<=0.18.12,>=0.18.7
|
18
18
|
Requires-Dist: djsuperadmin<1.0.0,>=0.9
|
19
19
|
Requires-Dist: djangorestframework<=3.14.0,>=3.10.0
|
20
|
-
Requires-Dist: django-structured-json-field>=1.1.
|
20
|
+
Requires-Dist: django-structured-json-field>=1.1.2
|
21
21
|
Requires-Dist: Pillow>=10.0.0
|
22
22
|
Requires-Dist: django-admin-interface<1.0.0,>=0.26.0
|
23
23
|
Requires-Dist: django-ckeditor<7.0.0,>=5.7.1
|
{django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/django_camomilla_cms.egg-info/SOURCES.txt
RENAMED
@@ -132,9 +132,14 @@ tests/test_models.py
|
|
132
132
|
tests/test_page_meta.py
|
133
133
|
tests/test_page_relation_api.py
|
134
134
|
tests/test_pages.py
|
135
|
+
tests/test_parsers.py
|
135
136
|
tests/test_query_parser.py
|
137
|
+
tests/test_sitemap.py
|
136
138
|
tests/test_templates_context.py
|
137
139
|
tests/test_utils.py
|
140
|
+
tests/test_utils_getters.py
|
141
|
+
tests/test_utils_normalization.py
|
142
|
+
tests/test_utils_setters.py
|
138
143
|
tests/fixtures/__init__.py
|
139
144
|
tests/utils/__init__.py
|
140
145
|
tests/utils/api.py
|
{django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/django_camomilla_cms.egg-info/requires.txt
RENAMED
@@ -1,7 +1,7 @@
|
|
1
1
|
django-modeltranslation<=0.18.12,>=0.18.7
|
2
2
|
djsuperadmin<1.0.0,>=0.9
|
3
3
|
djangorestframework<=3.14.0,>=3.10.0
|
4
|
-
django-structured-json-field>=1.1.
|
4
|
+
django-structured-json-field>=1.1.2
|
5
5
|
Pillow>=10.0.0
|
6
6
|
django-admin-interface<1.0.0,>=0.26.0
|
7
7
|
django-ckeditor<7.0.0,>=5.7.1
|
@@ -15,7 +15,7 @@ dependencies = [
|
|
15
15
|
"django-modeltranslation>=0.18.7,<=0.18.12",
|
16
16
|
"djsuperadmin>=0.9,<1.0.0",
|
17
17
|
"djangorestframework>=3.10.0,<=3.14.0",
|
18
|
-
"django-structured-json-field>=1.1.
|
18
|
+
"django-structured-json-field>=1.1.2",
|
19
19
|
"Pillow>=10.0.0",
|
20
20
|
"django-admin-interface>=0.26.0,<1.0.0",
|
21
21
|
"django-ckeditor>=5.7.1,<7.0.0",
|
@@ -60,3 +60,10 @@ prerelease = false
|
|
60
60
|
match = "next"
|
61
61
|
prerelease = true
|
62
62
|
prerelease_token = "beta"
|
63
|
+
|
64
|
+
[tool.semantic_release.changelog]
|
65
|
+
mode = "update"
|
66
|
+
|
67
|
+
[tool.semantic_release.changelog.default_templates]
|
68
|
+
changelog_file = "CHANGELOG.md"
|
69
|
+
output_format = "md"
|
@@ -36,7 +36,7 @@ class AdminPageFormTestCase(TestCase):
|
|
36
36
|
|
37
37
|
page_admin = PageAdmin(Page, AdminSite())
|
38
38
|
form = page_admin.get_form(request)()
|
39
|
-
self.assertEqual(len(list(form.fields)),
|
39
|
+
self.assertEqual(len(list(form.fields)), 35)
|
40
40
|
self.assertTrue("template" in list(form.fields))
|
41
41
|
self.assertListEqual(
|
42
42
|
form.fields["template"].widget.choices,
|
@@ -54,7 +54,7 @@ class AdminPageFormTestCase(TestCase):
|
|
54
54
|
|
55
55
|
page_admin = PageAdmin(Page, AdminSite())
|
56
56
|
form = page_admin.get_form(request_with_cookies)()
|
57
|
-
self.assertEqual(len(list(form.fields)),
|
57
|
+
self.assertEqual(len(list(form.fields)), 35)
|
58
58
|
self.assertTrue("template" in list(form.fields))
|
59
59
|
self.assertListEqual(
|
60
60
|
form.fields["template"].widget.choices,
|
{django_camomilla_cms-6.1.4 → django_camomilla_cms-6.2.1}/tests/test_model_api_permissions.py
RENAMED
@@ -9,14 +9,20 @@ client = APIClient()
|
|
9
9
|
def test_right_permissions():
|
10
10
|
response = client.post("/api/models/test-model/", {"title": "test"}, format="json")
|
11
11
|
assert response.status_code == 401
|
12
|
+
response = client.get("/api/models/test-model/")
|
13
|
+
assert response.status_code == 401
|
12
14
|
token = login_user()
|
13
15
|
client.credentials(HTTP_AUTHORIZATION="Token " + token)
|
14
16
|
response = client.post("/api/models/test-model/", {"title": "test"}, format="json")
|
15
17
|
assert response.status_code == 403
|
18
|
+
response = client.get("/api/models/test-model/")
|
19
|
+
assert response.status_code == 200
|
16
20
|
token = login_staff()
|
17
21
|
client.credentials(HTTP_AUTHORIZATION="Token " + token)
|
18
22
|
response = client.post("/api/models/test-model/", {"title": "test"}, format="json")
|
19
23
|
assert response.status_code == 403
|
24
|
+
response = client.get("/api/models/test-model/")
|
25
|
+
assert response.status_code == 200
|
20
26
|
token = login_superuser()
|
21
27
|
client.credentials(HTTP_AUTHORIZATION="Token " + token)
|
22
28
|
response = client.post("/api/models/test-model/", {"title": "test"}, format="json")
|
@@ -347,3 +347,21 @@ class PagesTestCase(TestCase):
|
|
347
347
|
response = self.client.get("/it/permalink_6_it/")
|
348
348
|
assert response.status_code == 301
|
349
349
|
assert response.url == "/it/permalink_6_it_changed/"
|
350
|
+
|
351
|
+
@pytest.mark.django_db
|
352
|
+
def test_page_keywords(self):
|
353
|
+
# Create page with keywords field and check it's given back as expected
|
354
|
+
response = self.client.post(
|
355
|
+
"/api/camomilla/pages/",
|
356
|
+
{
|
357
|
+
"og_description_it" : "Keywords Test",
|
358
|
+
"keywords_it" : 'key1, key2'
|
359
|
+
},
|
360
|
+
format="json",
|
361
|
+
)
|
362
|
+
|
363
|
+
assert response.status_code == 201
|
364
|
+
assert len(Page.objects.all()) == 1
|
365
|
+
page = Page.objects.first()
|
366
|
+
assert page.og_description_it == "Keywords Test"
|
367
|
+
assert page.keywords_it == 'key1, key2'
|