django-camomilla-cms 6.0.1__py2.py3-none-any.whl → 6.1.0__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/models/page.py +21 -2
- camomilla/serializers/page.py +4 -3
- camomilla/settings.py +7 -1
- camomilla/theme/__init__.py +1 -1
- camomilla/urls.py +3 -3
- camomilla/views/menus.py +8 -3
- camomilla/views/pages.py +4 -4
- {django_camomilla_cms-6.0.1.dist-info → django_camomilla_cms-6.1.0.dist-info}/METADATA +1 -1
- {django_camomilla_cms-6.0.1.dist-info → django_camomilla_cms-6.1.0.dist-info}/RECORD +16 -14
- tests/test_page_meta.py +88 -0
- tests/test_page_relation_api.py +77 -0
- tests/test_pages.py +2 -4
- {django_camomilla_cms-6.0.1.dist-info → django_camomilla_cms-6.1.0.dist-info}/WHEEL +0 -0
- {django_camomilla_cms-6.0.1.dist-info → django_camomilla_cms-6.1.0.dist-info}/licenses/LICENSE +0 -0
- {django_camomilla_cms-6.0.1.dist-info → django_camomilla_cms-6.1.0.dist-info}/top_level.txt +0 -0
camomilla/__init__.py
CHANGED
camomilla/models/page.py
CHANGED
@@ -29,6 +29,7 @@ from camomilla import settings
|
|
29
29
|
from camomilla.templates_context.rendering import ctx_registry
|
30
30
|
from django.conf import settings as django_settings
|
31
31
|
from modeltranslation.utils import build_localized_fieldname
|
32
|
+
from django.utils.module_loading import import_string
|
32
33
|
|
33
34
|
|
34
35
|
class UrlRedirect(models.Model):
|
@@ -287,6 +288,22 @@ class AbstractPage(SeoMixin, MetaMixin, models.Model, metaclass=PageBase):
|
|
287
288
|
context.update(new_ctx)
|
288
289
|
return ctx_registry.get_context_for_page(self, request, super_ctx=context)
|
289
290
|
|
291
|
+
@classmethod
|
292
|
+
def get_serializer(cls):
|
293
|
+
from camomilla.serializers.mixins import AbstractPageMixin
|
294
|
+
|
295
|
+
standard_serializer = (
|
296
|
+
pointed_getter(cls, "_page_meta.standard_serializer")
|
297
|
+
or settings.PAGES_DEFAULT_SERIALIZER
|
298
|
+
)
|
299
|
+
if isinstance(standard_serializer, str):
|
300
|
+
standard_serializer = import_string(standard_serializer)
|
301
|
+
if not issubclass(standard_serializer, AbstractPageMixin):
|
302
|
+
raise ValueError(
|
303
|
+
f"Standard serializer {standard_serializer} must be a subclass of AbstractPageMixin"
|
304
|
+
)
|
305
|
+
return standard_serializer
|
306
|
+
|
290
307
|
@property
|
291
308
|
def model_name(self) -> str:
|
292
309
|
return self._meta.app_label + "." + self._meta.model_name
|
@@ -356,7 +373,8 @@ class AbstractPage(SeoMixin, MetaMixin, models.Model, metaclass=PageBase):
|
|
356
373
|
def generate_permalink(self, safe: bool = True) -> str:
|
357
374
|
permalink = f"/{slugify(self.title or '', allow_unicode=True)}"
|
358
375
|
if self.parent:
|
359
|
-
|
376
|
+
parent_permalink = (self.parent.permalink or "").lstrip("/")
|
377
|
+
permalink = f"/{parent_permalink}{permalink}"
|
360
378
|
set_nofallbacks(self, "permalink", permalink)
|
361
379
|
qs = UrlNode.objects.exclude(pk=getattr(self.url_node or object, "pk", None))
|
362
380
|
if safe and qs.filter(permalink=permalink).exists():
|
@@ -455,7 +473,7 @@ class AbstractPage(SeoMixin, MetaMixin, models.Model, metaclass=PageBase):
|
|
455
473
|
preview = request and getattr(request, "GET", {}).get("preview", False)
|
456
474
|
permalinks = get_field_translations(self.url_node or object, "permalink", None)
|
457
475
|
for lang in activate_languages():
|
458
|
-
if lang in permalinks:
|
476
|
+
if lang in permalinks and permalinks[lang]:
|
459
477
|
permalinks[lang] = (
|
460
478
|
UrlNode.reverse_url(permalinks[lang])
|
461
479
|
if preview or self.is_public
|
@@ -475,6 +493,7 @@ class AbstractPage(SeoMixin, MetaMixin, models.Model, metaclass=PageBase):
|
|
475
493
|
parent_page_field = "parent_page"
|
476
494
|
default_template = settings.PAGE_DEFAULT_TEMPLATE
|
477
495
|
inject_context_func = settings.PAGE_INJECT_CONTEXT_FUNC
|
496
|
+
standard_serializer = settings.PAGES_DEFAULT_SERIALIZER
|
478
497
|
|
479
498
|
|
480
499
|
class Page(AbstractPage):
|
camomilla/serializers/page.py
CHANGED
@@ -22,7 +22,7 @@ class PageSerializer(AbstractPageMixin, BaseModelSerializer):
|
|
22
22
|
fields = "__all__"
|
23
23
|
|
24
24
|
|
25
|
-
class
|
25
|
+
class UrlNodeSerializer(BaseModelSerializer):
|
26
26
|
is_public = serializers.SerializerMethodField()
|
27
27
|
status = serializers.SerializerMethodField()
|
28
28
|
indexable = serializers.SerializerMethodField()
|
@@ -41,17 +41,18 @@ class BasicUrlNodeSerializer(BaseModelSerializer):
|
|
41
41
|
return instance.page.indexable
|
42
42
|
|
43
43
|
|
44
|
-
class UrlNodeSerializer
|
44
|
+
class RouteSerializer(UrlNodeSerializer):
|
45
45
|
alternates = serializers.SerializerMethodField()
|
46
46
|
|
47
47
|
def get_alternates(self, instance: UrlNode):
|
48
48
|
return instance.page.alternate_urls()
|
49
49
|
|
50
50
|
def to_representation(self, instance: UrlNode):
|
51
|
+
standard_serializer = instance.page.get_serializer()
|
51
52
|
model_serializer = build_standard_model_serializer(
|
52
53
|
instance.page.__class__,
|
53
54
|
depth=10,
|
54
|
-
bases=(
|
55
|
+
bases=(standard_serializer,) + get_standard_bases(),
|
55
56
|
)
|
56
57
|
return {
|
57
58
|
**super().to_representation(instance),
|
camomilla/settings.py
CHANGED
@@ -49,6 +49,12 @@ PAGE_INJECT_CONTEXT_FUNC = pointed_getter(
|
|
49
49
|
django_settings, "CAMOMILLA.RENDER.PAGE.INJECT_CONTEXT", None
|
50
50
|
)
|
51
51
|
|
52
|
+
PAGES_DEFAULT_SERIALIZER = pointed_getter(
|
53
|
+
django_settings,
|
54
|
+
"CAMOMILLA.API.PAGES.DEFAULT_SERIALIZER",
|
55
|
+
"camomilla.serializers.mixins.AbstractPageMixin",
|
56
|
+
)
|
57
|
+
|
52
58
|
ENABLE_TRANSLATIONS = (
|
53
59
|
ENABLE_REGISTRATIONS and "modeltranslation" in django_settings.INSTALLED_APPS
|
54
60
|
)
|
@@ -127,6 +133,6 @@ DEBUG = pointed_getter(django_settings, "CAMOMILLA.DEBUG", django_settings.DEBUG
|
|
127
133
|
# "URL": "http://localhost:4321"
|
128
134
|
# }
|
129
135
|
# }
|
130
|
-
# "API": {"NESTING_DEPTH": 10, "TRANSLATION_ACCESSOR": "translations"},
|
136
|
+
# "API": {"NESTING_DEPTH": 10, "TRANSLATION_ACCESSOR": "translations", "PAGES": {"DEFAULT_SERIALIZER": "camomilla.serializers.page.RouteSerializer"}},
|
131
137
|
# "DEBUG": False
|
132
138
|
# }
|
camomilla/theme/__init__.py
CHANGED
@@ -1 +1 @@
|
|
1
|
-
__version__ = "6.0
|
1
|
+
__version__ = "6.1.0"
|
camomilla/urls.py
CHANGED
@@ -19,7 +19,7 @@ from camomilla.views import (
|
|
19
19
|
UserViewSet,
|
20
20
|
MenuViewSet,
|
21
21
|
)
|
22
|
-
from camomilla.views.pages import
|
22
|
+
from camomilla.views.pages import pages_router
|
23
23
|
from camomilla.redirects import url_patterns as old_redirects
|
24
24
|
|
25
25
|
router = routers.DefaultRouter()
|
@@ -37,8 +37,8 @@ router.register(r"menus", MenuViewSet, "camomilla-menus")
|
|
37
37
|
urlpatterns = [
|
38
38
|
*old_redirects,
|
39
39
|
path("", include(router.urls)),
|
40
|
-
path("pages-router/",
|
41
|
-
path("pages-router/<path:permalink>",
|
40
|
+
path("pages-router/", pages_router),
|
41
|
+
path("pages-router/<path:permalink>", pages_router),
|
42
42
|
path("token-auth/", CamomillaObtainAuthToken.as_view(), name="api_token"),
|
43
43
|
path("auth/login/", CamomillaAuthLogin.as_view(), name="login"),
|
44
44
|
path("auth/logout/", CamomillaAuthLogout.as_view(), name="logout"),
|
camomilla/views/menus.py
CHANGED
@@ -9,7 +9,7 @@ from camomilla.models import AbstractPage, Menu
|
|
9
9
|
from camomilla.models.page import UrlNode
|
10
10
|
from camomilla.permissions import CamomillaBasePermissions
|
11
11
|
from camomilla.serializers import ContentTypeSerializer, MenuSerializer
|
12
|
-
from camomilla.serializers.page import
|
12
|
+
from camomilla.serializers.page import UrlNodeSerializer
|
13
13
|
from camomilla.views.base import BaseModelViewset
|
14
14
|
from camomilla.views.decorators import active_lang
|
15
15
|
|
@@ -66,7 +66,12 @@ class MenuViewSet(BaseModelViewset):
|
|
66
66
|
raise Http404("No object matches the given query.")
|
67
67
|
return Response(
|
68
68
|
[
|
69
|
-
{
|
69
|
+
{
|
70
|
+
"id": obj.pk,
|
71
|
+
"name": str(obj),
|
72
|
+
"url_node_id": obj.url_node.pk,
|
73
|
+
"model": f"{content_type.app_label}.{content_type.model}",
|
74
|
+
}
|
70
75
|
for obj in content_type.model_class().objects.exclude(
|
71
76
|
url_node__isnull=True
|
72
77
|
)
|
@@ -78,4 +83,4 @@ class MenuViewSet(BaseModelViewset):
|
|
78
83
|
def search_urlnode(self, request, *args, **kwargs):
|
79
84
|
url_node = request.GET.get("q", "")
|
80
85
|
qs = UrlNode.objects.filter(permalink__icontains=url_node).order_by("permalink")
|
81
|
-
return Response(
|
86
|
+
return Response(UrlNodeSerializer(qs, many=True).data)
|
camomilla/views/pages.py
CHANGED
@@ -2,7 +2,7 @@ from camomilla.models import Page
|
|
2
2
|
from camomilla.models.page import UrlNode, UrlRedirect
|
3
3
|
from camomilla.permissions import CamomillaBasePermissions
|
4
4
|
from camomilla.serializers import PageSerializer
|
5
|
-
from camomilla.serializers.page import
|
5
|
+
from camomilla.serializers.page import RouteSerializer
|
6
6
|
from camomilla.views.base import BaseModelViewset
|
7
7
|
from camomilla.views.decorators import active_lang
|
8
8
|
from camomilla.views.mixins import BulkDeleteMixin, GetUserLanguageMixin
|
@@ -26,10 +26,10 @@ class PageViewSet(GetUserLanguageMixin, BulkDeleteMixin, BaseModelViewset):
|
|
26
26
|
permissions.AllowAny,
|
27
27
|
]
|
28
28
|
)
|
29
|
-
def
|
29
|
+
def pages_router(request, permalink=""):
|
30
30
|
redirect = UrlRedirect.find_redirect_from_url(f"/{permalink}")
|
31
31
|
if redirect:
|
32
32
|
redirect = redirect.redirect()
|
33
33
|
return Response({"redirect": redirect.url, "status": redirect.status_code})
|
34
|
-
node = get_object_or_404(UrlNode, permalink=f"/{permalink}")
|
35
|
-
return Response(
|
34
|
+
node: UrlNode = get_object_or_404(UrlNode, permalink=f"/{permalink}")
|
35
|
+
return Response(RouteSerializer(node, context={"request": request}).data)
|
@@ -1,4 +1,4 @@
|
|
1
|
-
camomilla/__init__.py,sha256=
|
1
|
+
camomilla/__init__.py,sha256=R1pWTtcXHHHh0t0eJesB_UA9sQWaAVY2b2JPbeBk_68,243
|
2
2
|
camomilla/apps.py,sha256=eUwb9ynyiRAc5OXgt7ZsAdhsCOnPCpNdIFYMheNeN-o,532
|
3
3
|
camomilla/authentication.py,sha256=jz6tQT4PPEu-_JLox1LZrOy7EiWBb9MWaObK63MJGus,855
|
4
4
|
camomilla/context_processors.py,sha256=cGowjDZ-oDGYn1j2Pj5QDGCqnzXAOdOwp5dmzin_FTc,165
|
@@ -9,10 +9,10 @@ camomilla/model_api.py,sha256=-7l3fc2eN1itCMzkWA8nFaQXMmz0vs7IlGlShF-gSuo,2487
|
|
9
9
|
camomilla/parsers.py,sha256=fL8XGCGPxJIZNZkPdGtnPSbDP-6-yzGOCVMuLPjkx9Y,1975
|
10
10
|
camomilla/permissions.py,sha256=9NlBO4JMmg36vXCUjPNyq6uZxhkdrnXyIbJVLtWhGWE,1813
|
11
11
|
camomilla/redirects.py,sha256=ilcyHidb5Iw3jTrXMnPntr50kkl_WB3QOB0VNkIxP7A,263
|
12
|
-
camomilla/settings.py,sha256=
|
12
|
+
camomilla/settings.py,sha256=lEQPysEJZ_0c9Bkr1P38rO2csPrcNCdqeLqGp1aMS2I,4362
|
13
13
|
camomilla/sitemap.py,sha256=U2t5TwhB_-sEscmQZ69PZ5st3bIap8NRxzWEvCgB130,786
|
14
14
|
camomilla/translation.py,sha256=_QyfTlKG6hQ_ClRfxzeJ-3oI3Nu5peJN9xFkO9Ib3As,1316
|
15
|
-
camomilla/urls.py,sha256=
|
15
|
+
camomilla/urls.py,sha256=umWlVDJ_J4aPkqeSbHJznrGJi0marvWi8TfSmsRT5a0,2101
|
16
16
|
camomilla/contrib/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
17
17
|
camomilla/contrib/modeltranslation/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
18
18
|
camomilla/contrib/modeltranslation/hvad_migration.py,sha256=3j_q_Q85eF4iHbU4LG1Zr3LOmfmGmFiVSL-C8KvPsJQ,5409
|
@@ -28,7 +28,7 @@ camomilla/models/article.py,sha256=LgkZgRsubtDV6NwBz8E2bIgKD6H3I-1QLAxEan5TYYs,1
|
|
28
28
|
camomilla/models/content.py,sha256=mIgtifb_WMIt58we5u6qWZemHvuDN1zZaBeCyzHL78A,956
|
29
29
|
camomilla/models/media.py,sha256=pD-qldiHDOOHgux4lsivQLBcOJJrRx3a4Bg8ODNx7r0,6852
|
30
30
|
camomilla/models/menu.py,sha256=hUszPcn1prWCDhk4RPvbITmyhsB2CjFkaerx9t1GWnc,3766
|
31
|
-
camomilla/models/page.py,sha256=
|
31
|
+
camomilla/models/page.py,sha256=hL2txxJv5MScU-BsphZUYCybllNAEiR3Dd25c_AS35Y,19976
|
32
32
|
camomilla/models/mixins/__init__.py,sha256=c2NixqvrIX4E9WGRqQbylXlqBWDXEqN9mzs_dpB0hFQ,1248
|
33
33
|
camomilla/openapi/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
34
34
|
camomilla/openapi/schema.py,sha256=C22dhKjaJ2DTK4KWFjyMJXiwe8NLy7ZTW5d-I1dqZ7g,2546
|
@@ -37,7 +37,7 @@ camomilla/serializers/article.py,sha256=pYVcS0KztzjzSqgruElQMMEZcqTzmQUqXrdv_Sx5
|
|
37
37
|
camomilla/serializers/content_type.py,sha256=qB2wkmkvQI6LHxfSI6auEh6M9cJRFBaHnpmkBCCzeYo,557
|
38
38
|
camomilla/serializers/media.py,sha256=H4JVpRVxXVmn_BiqrjihKXpfLm9fLmHDFIICRDGJU4s,1940
|
39
39
|
camomilla/serializers/menu.py,sha256=TdoyXs40PqxNevnRbBbYOOX9rUv9zQGiHFNduspaZnw,552
|
40
|
-
camomilla/serializers/page.py,sha256=
|
40
|
+
camomilla/serializers/page.py,sha256=n2gfRkKXiQuCHEIGnJ2gC1sFsFitBxZ6WZ3bxpr_C5Q,1885
|
41
41
|
camomilla/serializers/user.py,sha256=CzrHiVRvYYWNE4eNpCNKtJB7DjVqHHwIcP4NUBXMHSo,3706
|
42
42
|
camomilla/serializers/utils.py,sha256=XRL4CNwQDBNpX8xT7365Dw2Cyx8Kvh18GaadgjS9awk,968
|
43
43
|
camomilla/serializers/validators.py,sha256=X2uBlh348nJjUWHPtiu9XKCD7Etsdg0811a4xHLAUzU,2103
|
@@ -73,7 +73,7 @@ camomilla/templatetags/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3
|
|
73
73
|
camomilla/templatetags/camomilla_filters.py,sha256=35x0-cWrRHeLhqypSLlJzEFY_fQDcRHiwZQpFgIsspE,692
|
74
74
|
camomilla/templatetags/menus.py,sha256=7fc4f9DDqtqG6wNb5_Q0km-fq0mqvGnbpR21qO1TJUw,960
|
75
75
|
camomilla/templatetags/model_extras.py,sha256=6WfVDYP_OfuVJd3cNGNA55Wj9uWdrbfOZQ0ua9Xt_vc,2257
|
76
|
-
camomilla/theme/__init__.py,sha256=
|
76
|
+
camomilla/theme/__init__.py,sha256=PD5agZ0_DXqsFLMBR0hacZV3LbzGbH8qn-j7MIAm3Xs,22
|
77
77
|
camomilla/theme/apps.py,sha256=Ue2H80fbFgxkQyHeU2H0fWs9Y6d-EnHYv4zz824FSRk,1066
|
78
78
|
camomilla/theme/admin/__init__.py,sha256=TALAZaE-gWshSeGc6yy7VahdX5UfeCeoOE9Q5kJCEpM,2270
|
79
79
|
camomilla/theme/admin/pages.py,sha256=HHi8dxjqffjMQGIRpOVNgQZhtKSSx3pFIctbqoZ9J2I,2614
|
@@ -97,8 +97,8 @@ camomilla/views/contents.py,sha256=JxvnmgeK8JEmCMLzVG8pVq2DwvmjXtgnIdsDnn74tA4,1
|
|
97
97
|
camomilla/views/decorators.py,sha256=hR--nTGQn2mMKDrWn-0Ildzbsvp11OfoWAtedKEzmiA,982
|
98
98
|
camomilla/views/languages.py,sha256=Rt_X7s3dbDBv4dxsQ9fnav_u0TAzzo8fGKBBx3esDsg,441
|
99
99
|
camomilla/views/medias.py,sha256=XYa-NTLLQmSSynpfrFT3av-K_r59aRns3dTGfYMj-0Q,3002
|
100
|
-
camomilla/views/menus.py,sha256=
|
101
|
-
camomilla/views/pages.py,sha256=
|
100
|
+
camomilla/views/menus.py,sha256=2uEeQc68wmmxiQ-mEG9wj1m18uF9f4oq-_5anAVOIbw,3449
|
101
|
+
camomilla/views/pages.py,sha256=GwLRcyrLqL3g4BFcbGQ2b0yspA-osA092zTMgVys56M,1345
|
102
102
|
camomilla/views/tags.py,sha256=XcYRlcBFSPPY32lt7POb6fWPJL_8HsTo5JcHcAOiOKw,479
|
103
103
|
camomilla/views/users.py,sha256=_fvsKOEtep4SJLvMva2_q-HdLQT_1KlFNt4wcl3xCJk,3130
|
104
104
|
camomilla/views/base/__init__.py,sha256=bpbVBGXLTy7No95XyDNB2U8hVXmwQJrF1VjLAS5WH90,1232
|
@@ -109,7 +109,7 @@ camomilla/views/mixins/optimize.py,sha256=iRPNkoeIIlJugk7DjJhDPaqeX7Opi7TxnUoMDn
|
|
109
109
|
camomilla/views/mixins/ordering.py,sha256=mh7fqPyVCVJh84Nl2pYFQouzGxa-ANF3Wqv0pCb7OVU,4779
|
110
110
|
camomilla/views/mixins/pagination.py,sha256=Ssa5mMgAgyl7sUk0yum2uVifg6esdGmUTqMSJYacE40,5772
|
111
111
|
camomilla/views/mixins/permissions.py,sha256=TPmR3Hoa3BjeJu9rCE_7lpLOAupue4WI42C21HTo6X4,200
|
112
|
-
django_camomilla_cms-6.0.
|
112
|
+
django_camomilla_cms-6.1.0.dist-info/licenses/LICENSE,sha256=kVS7zDrNkav2hLLXbOJwVdonY2ToApTK3khyJagGQoQ,1063
|
113
113
|
tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
114
114
|
tests/test_admin_page_form.py,sha256=DRJxekEKeYMCf9q62ax7iBeJGhEP2NZ8o02krZBR_DA,1971
|
115
115
|
tests/test_api.py,sha256=t03EFDezGgm4UJl8RIVvnTUkAGTB6ptm0G2lHBQ7ljc,1833
|
@@ -120,7 +120,9 @@ tests/test_model_api.py,sha256=ml3OlLuBfcnr2EMjwQLvVDPT2adSQ7WS4IxxXKD1InU,4121
|
|
120
120
|
tests/test_model_api_permissions.py,sha256=lUlcYAOasFFQjMFnqhGXlXriCH-f6xdYSCn1Gqf1eSU,1838
|
121
121
|
tests/test_model_api_register.py,sha256=txKaVTGt-DGrmI-6xcUEluPd7ArNi80VvlqBVXdH8zk,13555
|
122
122
|
tests/test_models.py,sha256=WJs8lxWZWn1l7X3a_QFVc8fF5LHTsI8bc3uhQe6-o-Q,684
|
123
|
-
tests/
|
123
|
+
tests/test_page_meta.py,sha256=QFmX97LBYSuHn9vJPM80MWZc3BwfGO5V-sCClk7ExOA,3142
|
124
|
+
tests/test_page_relation_api.py,sha256=PrFY3vuuFal4og8MUq8ba02qITsNOtIP1eNmQ_f9jxk,2760
|
125
|
+
tests/test_pages.py,sha256=Zo1dV6Ie2hPPfc2V7uPbVW9gEtuBWOGypglaVIbTG98,11885
|
124
126
|
tests/test_query_parser.py,sha256=R9l0L2QDEDcm2b6IFUhyf7wMXLzL9RySLkzKTWRtBkE,2097
|
125
127
|
tests/test_templates_context.py,sha256=zGdmbQMGNXB2V_15BaQDIgqFMnVjBAw969n1tu3m7HY,5626
|
126
128
|
tests/test_utils.py,sha256=ow4csGfU5WzMgAT5zWjZIxZwW1-BqnMduDt8hOzf9cE,2166
|
@@ -128,7 +130,7 @@ tests/fixtures/__init__.py,sha256=ixyA6ZsmYbiKEsjQGOGoG4KyJmwWrf-qeoQjQG3J66U,42
|
|
128
130
|
tests/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
129
131
|
tests/utils/api.py,sha256=TYcDXeILHtBwzwG0acwPFmiqMZnlF9VnLB0Ydhg55vA,865
|
130
132
|
tests/utils/media.py,sha256=-cnrQzzVuhNSb5rT5xMUs5f3yYpBnS0fVGDcjgsb8lw,291
|
131
|
-
django_camomilla_cms-6.0.
|
132
|
-
django_camomilla_cms-6.0.
|
133
|
-
django_camomilla_cms-6.0.
|
134
|
-
django_camomilla_cms-6.0.
|
133
|
+
django_camomilla_cms-6.1.0.dist-info/METADATA,sha256=mA_yBZVvW76HuYxBelBObDFK6c7kztUJ67Svwps6gFY,5652
|
134
|
+
django_camomilla_cms-6.1.0.dist-info/WHEEL,sha256=JNWh1Fm1UdwIQV075glCn4MVuCRs0sotJIq-J6rbxCU,109
|
135
|
+
django_camomilla_cms-6.1.0.dist-info/top_level.txt,sha256=G9VIGBmMMqC7JEckoTgXKmC6T2BR75QRkqRnngw1_lo,16
|
136
|
+
django_camomilla_cms-6.1.0.dist-info/RECORD,,
|
tests/test_page_meta.py
ADDED
@@ -0,0 +1,88 @@
|
|
1
|
+
import pytest
|
2
|
+
from django.test import TestCase
|
3
|
+
from rest_framework.test import APIClient
|
4
|
+
|
5
|
+
from tests.utils.media import load_asset_and_remove_media
|
6
|
+
from .utils.api import login_superuser
|
7
|
+
from camomilla.models import Page, Media
|
8
|
+
from example.website.models import CustomPageMetaModel, InvalidPageMetaModel
|
9
|
+
|
10
|
+
|
11
|
+
class PagaMetaTestCase(TestCase):
|
12
|
+
def setUp(self):
|
13
|
+
self.client = APIClient()
|
14
|
+
token = login_superuser()
|
15
|
+
self.client.credentials(HTTP_AUTHORIZATION="Token " + token)
|
16
|
+
|
17
|
+
@pytest.mark.django_db
|
18
|
+
def test_page_meta_rendering(self):
|
19
|
+
asset = load_asset_and_remove_media("37059501.png")
|
20
|
+
Media.objects.create(
|
21
|
+
file=asset,
|
22
|
+
alt_text="Test Media",
|
23
|
+
title="Test Media",
|
24
|
+
description="Description of test media",
|
25
|
+
)
|
26
|
+
page = CustomPageMetaModel.objects.create(
|
27
|
+
title="Test Page",
|
28
|
+
custom_field="Custom Data",
|
29
|
+
permalink="test-page",
|
30
|
+
status="PUB",
|
31
|
+
autopermalink=False,
|
32
|
+
)
|
33
|
+
page.save()
|
34
|
+
response = self.client.get("/test-page/")
|
35
|
+
assert response.status_code == 200
|
36
|
+
content = response.content.decode()
|
37
|
+
assert "👻 I'm beeing injected!" in content
|
38
|
+
assert "<h1>I'm the custom template!</h1>" in content
|
39
|
+
assert "<ul><li>Test Media</li></ul>" in content
|
40
|
+
|
41
|
+
@pytest.mark.django_db
|
42
|
+
def test_page_meta_custom_parent_page(self):
|
43
|
+
parent_page = Page.objects.create(
|
44
|
+
title="Parent Page",
|
45
|
+
permalink="parent-page",
|
46
|
+
status="PUB",
|
47
|
+
autopermalink=False,
|
48
|
+
)
|
49
|
+
child_page = CustomPageMetaModel.objects.create(
|
50
|
+
title="Child Page",
|
51
|
+
custom_field="Child Data",
|
52
|
+
status="PUB",
|
53
|
+
custom_parent_page=parent_page,
|
54
|
+
)
|
55
|
+
assert child_page.permalink == "/parent-page/child-page"
|
56
|
+
|
57
|
+
@pytest.mark.django_db
|
58
|
+
def test_page_meta_custom_serializer(self):
|
59
|
+
|
60
|
+
CustomPageMetaModel.objects.create(
|
61
|
+
title="Test Page with Custom Serializer",
|
62
|
+
custom_field="Custom Data",
|
63
|
+
permalink="test-page-custom-serializer",
|
64
|
+
status="PUB",
|
65
|
+
autopermalink=False,
|
66
|
+
)
|
67
|
+
|
68
|
+
response = self.client.get(
|
69
|
+
"/api/camomilla/pages-router/test-page-custom-serializer"
|
70
|
+
)
|
71
|
+
assert response.status_code == 200
|
72
|
+
data = response.json()
|
73
|
+
assert data["title"] == "Test Page with Custom Serializer"
|
74
|
+
assert data["custom_field"] == "Custom Data"
|
75
|
+
assert data["permalink"] == "/test-page-custom-serializer"
|
76
|
+
assert (
|
77
|
+
data["serializer_custom_field"]
|
78
|
+
== "I'm coming from CustomPageSerializer! 🫡"
|
79
|
+
)
|
80
|
+
|
81
|
+
@pytest.mark.django_db
|
82
|
+
def test_page_meta_custom_serializer_error(self):
|
83
|
+
with pytest.raises(ValueError) as exc_info:
|
84
|
+
InvalidPageMetaModel.get_serializer()
|
85
|
+
assert (
|
86
|
+
str(exc_info.value)
|
87
|
+
== "Standard serializer <class 'example.website.serializers.InvalidSerializer'> must be a subclass of AbstractPageMixin"
|
88
|
+
)
|
@@ -0,0 +1,77 @@
|
|
1
|
+
from django.test import TestCase
|
2
|
+
from rest_framework.test import APIClient
|
3
|
+
from .utils.api import login_superuser
|
4
|
+
from example.website.models import (
|
5
|
+
ExposedRelatedPageModel,
|
6
|
+
UnexposedRelatedPageModel,
|
7
|
+
RelatedPageModel,
|
8
|
+
)
|
9
|
+
|
10
|
+
client = APIClient()
|
11
|
+
|
12
|
+
|
13
|
+
class PageRelationApi(TestCase):
|
14
|
+
def setUp(self):
|
15
|
+
token = login_superuser()
|
16
|
+
client.credentials(HTTP_AUTHORIZATION="Token " + token)
|
17
|
+
|
18
|
+
def test_exposed_relation(self):
|
19
|
+
exposed_related_page_model = ExposedRelatedPageModel.objects.create(
|
20
|
+
title="ExposedRelatedPageModel 1",
|
21
|
+
permalink="exposed-related-page-model-1",
|
22
|
+
status="PUB",
|
23
|
+
autopermalink=False,
|
24
|
+
)
|
25
|
+
related_page_model = RelatedPageModel.objects.create(
|
26
|
+
title="RelatedPageModel 1",
|
27
|
+
permalink="related-page-model-1",
|
28
|
+
status="PUB",
|
29
|
+
autopermalink=False,
|
30
|
+
)
|
31
|
+
related_page_model.exposed_pages.add(exposed_related_page_model)
|
32
|
+
related_page_model.save()
|
33
|
+
|
34
|
+
response = client.get("/api/camomilla/pages-router/related-page-model-1")
|
35
|
+
assert response.status_code == 200
|
36
|
+
data = response.json()
|
37
|
+
assert data["exposed_pages"][0]["id"] == exposed_related_page_model.id
|
38
|
+
|
39
|
+
response = client.get(
|
40
|
+
"/api/camomilla/pages-router/exposed-related-page-model-1"
|
41
|
+
)
|
42
|
+
assert response.status_code == 200
|
43
|
+
data = response.json()
|
44
|
+
assert (
|
45
|
+
"related_pages" in data
|
46
|
+
), "Exposed related pages should be included in the API response"
|
47
|
+
|
48
|
+
def test_unexposed_relation(self):
|
49
|
+
unexposed_related_page_model = UnexposedRelatedPageModel.objects.create(
|
50
|
+
title="UnexposedRelatedPageModel 1",
|
51
|
+
permalink="unexposed-related-page-model-1",
|
52
|
+
status="PUB",
|
53
|
+
autopermalink=False,
|
54
|
+
)
|
55
|
+
related_page_model = RelatedPageModel.objects.create(
|
56
|
+
title="RelatedPageModel 1",
|
57
|
+
permalink="related-page-model-1",
|
58
|
+
status="PUB",
|
59
|
+
autopermalink=False,
|
60
|
+
)
|
61
|
+
|
62
|
+
related_page_model.unexposed_pages.add(unexposed_related_page_model)
|
63
|
+
related_page_model.save()
|
64
|
+
|
65
|
+
response = client.get("/api/camomilla/pages-router/related-page-model-1")
|
66
|
+
assert response.status_code == 200
|
67
|
+
data = response.json()
|
68
|
+
assert data["unexposed_pages"][0]["id"] == unexposed_related_page_model.id
|
69
|
+
|
70
|
+
response = client.get(
|
71
|
+
"/api/camomilla/pages-router/unexposed-related-page-model-1"
|
72
|
+
)
|
73
|
+
assert response.status_code == 200
|
74
|
+
data = response.json()
|
75
|
+
assert (
|
76
|
+
"related_pages" not in data
|
77
|
+
), "Unexposed related pages should not be included in the API response"
|
tests/test_pages.py
CHANGED
@@ -165,13 +165,11 @@ class PagesTestCase(TestCase):
|
|
165
165
|
# EN parent page with automatic url creation
|
166
166
|
response = self.client.get("/api/camomilla/pages/3/?language=en")
|
167
167
|
assert response.json()["autopermalink"] == True
|
168
|
-
assert response.json()["permalink"] == "
|
168
|
+
assert response.json()["permalink"] == "/permalink_manual_en_2/title_page_3"
|
169
169
|
# IT parent page with automatic url creation
|
170
170
|
response = self.client.get("/api/camomilla/pages/3/?language=it")
|
171
171
|
assert response.json()["autopermalink"] == True
|
172
|
-
assert (
|
173
|
-
response.json()["permalink"] == "//permalink_manuale_it_2/titolo_pagina_3"
|
174
|
-
)
|
172
|
+
assert response.json()["permalink"] == "/permalink_manuale_it_2/titolo_pagina_3"
|
175
173
|
|
176
174
|
# Check url uniqueness and consistency EN
|
177
175
|
response = self.client.post(
|
File without changes
|
{django_camomilla_cms-6.0.1.dist-info → django_camomilla_cms-6.1.0.dist-info}/licenses/LICENSE
RENAMED
File without changes
|
File without changes
|