django-camomilla-cms 6.0.0b3__tar.gz → 6.0.0b4__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.0.0b3/django_camomilla_cms.egg-info → django-camomilla-cms-6.0.0b4}/PKG-INFO +1 -1
- {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/__init__.py +1 -1
- {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/contrib/rest_framework/serializer.py +30 -0
- {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/models/page.py +18 -7
- {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/serializers/mixins/__init__.py +16 -0
- django-camomilla-cms-6.0.0b4/camomilla/serializers/page.py +63 -0
- django-camomilla-cms-6.0.0b4/camomilla/serializers/utils.py +35 -0
- {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/settings.py +7 -0
- {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/structured/cache.py +3 -0
- django-camomilla-cms-6.0.0b4/camomilla/theme/__init__.py +1 -0
- {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/urls.py +3 -0
- django-camomilla-cms-6.0.0b4/camomilla/views/decorators.py +26 -0
- {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/views/menus.py +42 -0
- django-camomilla-cms-6.0.0b4/camomilla/views/pages.py +25 -0
- {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4/django_camomilla_cms.egg-info}/PKG-INFO +1 -1
- {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/django_camomilla_cms.egg-info/SOURCES.txt +1 -0
- {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/setup.py +1 -1
- django-camomilla-cms-6.0.0b3/camomilla/serializers/page.py +0 -15
- django-camomilla-cms-6.0.0b3/camomilla/serializers/utils.py +0 -30
- django-camomilla-cms-6.0.0b3/camomilla/theme/__init__.py +0 -1
- django-camomilla-cms-6.0.0b3/camomilla/views/pages.py +0 -12
- {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/LICENSE +0 -0
- {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/MANIFEST.in +0 -0
- {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/README.md +0 -0
- {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/apps.py +0 -0
- {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/authentication.py +0 -0
- {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/context_processors.py +0 -0
- {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/contrib/__init__.py +0 -0
- {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/contrib/modeltranslation/__init__.py +0 -0
- {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/contrib/modeltranslation/hvad_migration.py +0 -0
- {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/contrib/rest_framework/__init__.py +0 -0
- {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/defaults.py +0 -0
- {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/dynamic_pages_urls.py +0 -0
- {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/exceptions.py +0 -0
- {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/fields/__init__.py +0 -0
- {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/fields/json.py +0 -0
- {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/management/__init__.py +0 -0
- {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/management/commands/__init__.py +0 -0
- {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/management/commands/regenerate_thumbnails.py +0 -0
- {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/model_api.py +0 -0
- {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/models/__init__.py +0 -0
- {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/models/article.py +0 -0
- {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/models/content.py +0 -0
- {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/models/media.py +0 -0
- {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/models/menu.py +0 -0
- {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/models/mixins/__init__.py +0 -0
- {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/openapi/__init__.py +0 -0
- {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/openapi/schema.py +0 -0
- {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/parsers.py +0 -0
- {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/permissions.py +0 -0
- {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/serializers/__init__.py +0 -0
- {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/serializers/article.py +0 -0
- {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/serializers/base/__init__.py +0 -0
- {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/serializers/content_type.py +0 -0
- {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/serializers/fields/__init__.py +0 -0
- {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/serializers/fields/file.py +0 -0
- {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/serializers/fields/json.py +0 -0
- {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/serializers/fields/related.py +0 -0
- {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/serializers/media.py +0 -0
- {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/serializers/menu.py +0 -0
- {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/serializers/user.py +0 -0
- {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/serializers/validators.py +0 -0
- {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/storages/__init__.py +0 -0
- {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/storages/optimize.py +0 -0
- {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/storages/overwrite.py +0 -0
- {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/structured/__init__.py +0 -0
- {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/structured/fields.py +0 -0
- {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/structured/models.py +0 -0
- {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/structured/utils.py +0 -0
- {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/templates/admin/camomilla/page/change_form.html +0 -0
- {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/templates/defaults/articles/default.html +0 -0
- {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/templates/defaults/base.html +0 -0
- {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/templates/defaults/pages/default.html +0 -0
- {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/templates/defaults/parts/langswitch.html +0 -0
- {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/templates/defaults/parts/menu.html +0 -0
- {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/templates/defaults/widgets/media_select_multiple.html +0 -0
- {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/templatetags/__init__.py +0 -0
- {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/templatetags/camomilla_filters.py +0 -0
- {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/templatetags/menus.py +0 -0
- {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/theme/admin.py +0 -0
- {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/theme/apps.py +0 -0
- {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/theme/static/admin/css/responsive.css +0 -0
- {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/theme/static/admin/img/favicon.ico +0 -0
- {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/theme/static/admin/img/logo.svg +0 -0
- {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/theme/templates/admin/base.html +0 -0
- {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/theme/templates/rosetta/base.html +0 -0
- {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/translation.py +0 -0
- {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/utils/__init__.py +0 -0
- {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/utils/getters.py +0 -0
- {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/utils/normalization.py +0 -0
- {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/utils/seo.py +0 -0
- {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/utils/templates.py +0 -0
- {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/utils/translation.py +0 -0
- {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/views/__init__.py +0 -0
- {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/views/articles.py +0 -0
- {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/views/base/__init__.py +0 -0
- {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/views/contents.py +0 -0
- {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/views/languages.py +0 -0
- {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/views/medias.py +0 -0
- {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/views/mixins/__init__.py +0 -0
- {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/views/mixins/ordering.py +0 -0
- {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/views/mixins/pagination.py +0 -0
- {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/views/tags.py +0 -0
- {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/views/users.py +0 -0
- {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/django_camomilla_cms.egg-info/dependency_links.txt +0 -0
- {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/django_camomilla_cms.egg-info/requires.txt +0 -0
- {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/django_camomilla_cms.egg-info/top_level.txt +0 -0
- {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/setup.cfg +0 -0
- {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/tests/__init__.py +0 -0
- {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/tests/test_api.py +0 -0
- {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/tests/test_camomilla_filters.py +0 -0
- {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/tests/test_models.py +0 -0
- {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/tests/test_utils.py +0 -0
- {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/tests/urls.py +0 -0
@@ -77,3 +77,33 @@ class TranslationsMixin(serializers.ModelSerializer):
|
|
77
77
|
@property
|
78
78
|
def is_translatable(self):
|
79
79
|
return is_translatable(pointed_getter(self, "Meta.model"))
|
80
|
+
|
81
|
+
|
82
|
+
class RemoveTranslationsMixin(serializers.ModelSerializer):
|
83
|
+
@cached_property
|
84
|
+
def translation_fields(self):
|
85
|
+
try:
|
86
|
+
return translator.get_options_for_model(self.Meta.model).get_field_names()
|
87
|
+
except NotRegistered:
|
88
|
+
return []
|
89
|
+
|
90
|
+
def get_default_field_names(self, declared_fields, model_info):
|
91
|
+
request = self.context.get("request", False)
|
92
|
+
included_translations = request and request.GET.get(
|
93
|
+
"included_translations", False
|
94
|
+
)
|
95
|
+
if included_translations == "all":
|
96
|
+
return super().get_default_field_names(declared_fields, model_info)
|
97
|
+
elif included_translations is not False:
|
98
|
+
included_translations = included_translations.split(",")
|
99
|
+
else:
|
100
|
+
included_translations = []
|
101
|
+
|
102
|
+
field_names = super().get_default_field_names(declared_fields, model_info)
|
103
|
+
for lang in mt_settings.AVAILABLE_LANGUAGES:
|
104
|
+
if lang not in included_translations:
|
105
|
+
for field in self.translation_fields:
|
106
|
+
localized_fieldname = build_localized_fieldname(field, lang)
|
107
|
+
if localized_fieldname in field_names:
|
108
|
+
field_names.remove(localized_fieldname)
|
109
|
+
return field_names
|
@@ -98,14 +98,18 @@ class UrlNode(models.Model):
|
|
98
98
|
def page(self) -> "AbstractPage":
|
99
99
|
return getattr(self, self.related_name)
|
100
100
|
|
101
|
-
@
|
102
|
-
def
|
101
|
+
@staticmethod
|
102
|
+
def reverse_url(permalink: str) -> str:
|
103
103
|
try:
|
104
|
-
if
|
104
|
+
if permalink == "/":
|
105
105
|
return reverse("camomilla-homepage")
|
106
|
-
return reverse("camomilla-permalink", args=(
|
106
|
+
return reverse("camomilla-permalink", args=(permalink.lstrip("/"),))
|
107
107
|
except NoReverseMatch:
|
108
|
-
return
|
108
|
+
return None
|
109
|
+
|
110
|
+
@property
|
111
|
+
def routerlink(self) -> str:
|
112
|
+
return self.reverse_url(self.permalink) or self.permalink
|
109
113
|
|
110
114
|
|
111
115
|
PAGE_CHILD_RELATED_NAME = "%(app_label)s_%(class)s_child_pages"
|
@@ -306,7 +310,10 @@ class AbstractPage(SeoMixin, MetaMixin, models.Model, metaclass=PageBase):
|
|
306
310
|
bases += (cls.DoesNotExist,)
|
307
311
|
message = "%s matching query does not exist." % cls._meta.object_name
|
308
312
|
if public_error:
|
309
|
-
message =
|
313
|
+
message = (
|
314
|
+
"Match found: %s.\nThe page appears not to be public.\nUse ?preview=true in the url to see it."
|
315
|
+
% page
|
316
|
+
)
|
310
317
|
raise type("PageDoesNotExist", bases, {})(message)
|
311
318
|
return page
|
312
319
|
|
@@ -338,7 +345,11 @@ class AbstractPage(SeoMixin, MetaMixin, models.Model, metaclass=PageBase):
|
|
338
345
|
raise Http404(ex)
|
339
346
|
|
340
347
|
def alternate_urls(self, *args, **kwargs) -> dict:
|
341
|
-
|
348
|
+
permalinks = get_field_translations(self.url_node or object, "permalink", None)
|
349
|
+
for lang in activate_languages():
|
350
|
+
if lang in permalinks:
|
351
|
+
permalinks[lang] = UrlNode.reverse_url(permalinks[lang])
|
352
|
+
return permalinks
|
342
353
|
|
343
354
|
class Meta:
|
344
355
|
abstract = True
|
@@ -20,6 +20,9 @@ if django.VERSION >= (4, 0):
|
|
20
20
|
else:
|
21
21
|
from django.contrib.postgres.fields import JSONField as DjangoJSONField
|
22
22
|
|
23
|
+
from typing import TYPE_CHECKING
|
24
|
+
if TYPE_CHECKING:
|
25
|
+
from camomilla.models.page import AbstractPage
|
23
26
|
|
24
27
|
# TODO: decide what to do with LangInfoMixin mixin!
|
25
28
|
class LangInfoMixin(metaclass=serializers.SerializerMetaclass):
|
@@ -122,6 +125,16 @@ class NestMixin:
|
|
122
125
|
|
123
126
|
|
124
127
|
class AbstractPageMixin(serializers.ModelSerializer):
|
128
|
+
breadcrumbs = serializers.SerializerMethodField()
|
129
|
+
routerlink = serializers.CharField(read_only=True)
|
130
|
+
template = serializers.SerializerMethodField()
|
131
|
+
|
132
|
+
def get_template(self, instance: 'AbstractPage'):
|
133
|
+
return instance.get_template_path()
|
134
|
+
|
135
|
+
def get_breadcrumbs(self, instance: 'AbstractPage'):
|
136
|
+
return instance.breadcrumbs
|
137
|
+
|
125
138
|
LANG_PERMALINK_FIELDS = [
|
126
139
|
build_localized_fieldname("permalink", lang)
|
127
140
|
for lang in AVAILABLE_LANGUAGES
|
@@ -133,6 +146,9 @@ class AbstractPageMixin(serializers.ModelSerializer):
|
|
133
146
|
return super().translation_fields + ["permalink"]
|
134
147
|
|
135
148
|
def get_default_field_names(self, *args):
|
149
|
+
from camomilla.contrib.rest_framework.serializer import RemoveTranslationsMixin
|
150
|
+
if RemoveTranslationsMixin in self.__class__.__bases__: # noqa: E501
|
151
|
+
return super().get_default_field_names(*args)
|
136
152
|
return (
|
137
153
|
[f for f in super().get_default_field_names(*args) if f != "url_node"]
|
138
154
|
+ self.LANG_PERMALINK_FIELDS
|
@@ -0,0 +1,63 @@
|
|
1
|
+
from camomilla.models.page import UrlNode
|
2
|
+
from camomilla.serializers.mixins import AbstractPageMixin
|
3
|
+
from camomilla.models import Content, Page
|
4
|
+
from camomilla.serializers.base import BaseModelSerializer
|
5
|
+
from rest_framework import serializers
|
6
|
+
|
7
|
+
from camomilla.serializers.utils import (
|
8
|
+
build_standard_model_serializer,
|
9
|
+
get_standard_bases,
|
10
|
+
)
|
11
|
+
|
12
|
+
|
13
|
+
class ContentSerializer(BaseModelSerializer):
|
14
|
+
class Meta:
|
15
|
+
model = Content
|
16
|
+
fields = "__all__"
|
17
|
+
|
18
|
+
|
19
|
+
class PageSerializer(AbstractPageMixin, BaseModelSerializer):
|
20
|
+
class Meta:
|
21
|
+
model = Page
|
22
|
+
fields = "__all__"
|
23
|
+
|
24
|
+
|
25
|
+
class BasicUrlNodeSerializer(BaseModelSerializer):
|
26
|
+
is_public = serializers.SerializerMethodField()
|
27
|
+
status = serializers.SerializerMethodField()
|
28
|
+
indexable = serializers.SerializerMethodField()
|
29
|
+
|
30
|
+
class Meta:
|
31
|
+
model = UrlNode
|
32
|
+
fields = ("id", "permalink", "status", "indexable", "is_public")
|
33
|
+
|
34
|
+
def get_is_public(self, instance: UrlNode):
|
35
|
+
return instance.page.is_public
|
36
|
+
|
37
|
+
def get_status(self, instance: UrlNode):
|
38
|
+
return instance.page.status
|
39
|
+
|
40
|
+
def get_indexable(self, instance: UrlNode):
|
41
|
+
return instance.page.indexable
|
42
|
+
|
43
|
+
|
44
|
+
class UrlNodeSerializer(BasicUrlNodeSerializer):
|
45
|
+
alternates = serializers.SerializerMethodField()
|
46
|
+
|
47
|
+
def get_alternates(self, instance: UrlNode):
|
48
|
+
return instance.page.alternate_urls()
|
49
|
+
|
50
|
+
def to_representation(self, instance: UrlNode):
|
51
|
+
model_serializer = build_standard_model_serializer(
|
52
|
+
instance.page.__class__,
|
53
|
+
depth=10,
|
54
|
+
bases=(AbstractPageMixin,) + get_standard_bases(),
|
55
|
+
)
|
56
|
+
return {
|
57
|
+
**super().to_representation(instance),
|
58
|
+
**model_serializer(instance.page, context=self.context).data,
|
59
|
+
}
|
60
|
+
|
61
|
+
class Meta:
|
62
|
+
model = UrlNode
|
63
|
+
fields = "__all__"
|
@@ -0,0 +1,35 @@
|
|
1
|
+
def get_standard_bases() -> tuple:
|
2
|
+
from rest_framework.serializers import ModelSerializer
|
3
|
+
from camomilla.serializers.fields import FieldsOverrideMixin
|
4
|
+
from camomilla.contrib.rest_framework.serializer import RemoveTranslationsMixin
|
5
|
+
from camomilla.serializers.mixins import (
|
6
|
+
JSONFieldPatchMixin,
|
7
|
+
NestMixin,
|
8
|
+
OrderingMixin,
|
9
|
+
SetupEagerLoadingMixin,
|
10
|
+
)
|
11
|
+
|
12
|
+
return (
|
13
|
+
NestMixin,
|
14
|
+
FieldsOverrideMixin,
|
15
|
+
JSONFieldPatchMixin,
|
16
|
+
OrderingMixin,
|
17
|
+
RemoveTranslationsMixin,
|
18
|
+
SetupEagerLoadingMixin,
|
19
|
+
ModelSerializer,
|
20
|
+
)
|
21
|
+
|
22
|
+
def build_standard_model_serializer(model, depth, bases=None):
|
23
|
+
if bases is None:
|
24
|
+
bases = get_standard_bases()
|
25
|
+
return type(
|
26
|
+
f"{model.__name__}StandardSerializer",
|
27
|
+
bases,
|
28
|
+
{
|
29
|
+
"Meta": type(
|
30
|
+
"Meta",
|
31
|
+
(object,),
|
32
|
+
{"model": model, "depth": depth, "fields": "__all__"},
|
33
|
+
)
|
34
|
+
},
|
35
|
+
)
|
@@ -75,6 +75,10 @@ TEMPLATE_CONTEXT_FILES = pointed_getter(
|
|
75
75
|
django_settings, "CAMOMILLA.RENDER.TEMPLATE_CONTEXT_FILES", []
|
76
76
|
)
|
77
77
|
|
78
|
+
STRUCTURED_FIELD_CACHE_ENABLED = pointed_getter(
|
79
|
+
django_settings, "CAMOMILLA.STRUCTURED_FIELD.CACHE_ENABLED", True
|
80
|
+
)
|
81
|
+
|
78
82
|
DEBUG = pointed_getter(django_settings, "CAMOMILLA.DEBUG", django_settings.DEBUG)
|
79
83
|
|
80
84
|
# camomilla settings example
|
@@ -93,6 +97,9 @@ DEBUG = pointed_getter(django_settings, "CAMOMILLA.DEBUG", django_settings.DEBUG
|
|
93
97
|
# "ARTICLE": {"DEFAULT_TEMPLATE": "", "INJECT_CONTEXT": None },
|
94
98
|
# "PAGE": {"DEFAULT_TEMPLATE": "", "INJECT_CONTEXT": None }
|
95
99
|
# },
|
100
|
+
# "STRUCTURED_FIELD": {
|
101
|
+
# "CACHE_ENABLED": True
|
102
|
+
# }
|
96
103
|
# "API": {"NESTING_DEPTH": 10 },
|
97
104
|
# "DEBUG": False
|
98
105
|
# }
|
@@ -2,6 +2,7 @@ from collections import defaultdict
|
|
2
2
|
from inspect import isclass
|
3
3
|
from typing import Any, Dict, Sequence
|
4
4
|
from typing_extensions import get_args, get_origin
|
5
|
+
from camomilla.settings import STRUCTURED_FIELD_CACHE_ENABLED
|
5
6
|
from camomilla.structured.fields import ForeignKey, QuerySet
|
6
7
|
from camomilla.structured.models import BaseModel
|
7
8
|
from camomilla.structured.utils import _LazyType, get_type, pointed_setter
|
@@ -161,6 +162,8 @@ class CacheBuilder:
|
|
161
162
|
return fk_data
|
162
163
|
|
163
164
|
def inject_cache(self, data: Any) -> Any:
|
165
|
+
if not STRUCTURED_FIELD_CACHE_ENABLED:
|
166
|
+
return data
|
164
167
|
fk_data = self.get_all_fk_data(data)
|
165
168
|
plainset = defaultdict(set)
|
166
169
|
for model, touples in fk_data.items():
|
@@ -0,0 +1 @@
|
|
1
|
+
__version__ = "6.0.0-beta.4"
|
@@ -20,6 +20,7 @@ from camomilla.views import (
|
|
20
20
|
UserViewSet,
|
21
21
|
MenuViewSet,
|
22
22
|
)
|
23
|
+
from camomilla.views.pages import fetch_page
|
23
24
|
|
24
25
|
router = routers.DefaultRouter()
|
25
26
|
|
@@ -36,6 +37,8 @@ router.register(r"menus", MenuViewSet, "camomilla-menus")
|
|
36
37
|
|
37
38
|
urlpatterns = [
|
38
39
|
path("", include(router.urls)),
|
40
|
+
path("pages-router/", fetch_page),
|
41
|
+
path("pages-router/<path:permalink>", fetch_page),
|
39
42
|
path(
|
40
43
|
"profiles/me/", lambda _: redirect("../../users/current/"), name="profiles-me"
|
41
44
|
),
|
@@ -0,0 +1,26 @@
|
|
1
|
+
import functools
|
2
|
+
from django.utils.translation import activate
|
3
|
+
from django.conf import settings
|
4
|
+
|
5
|
+
|
6
|
+
def active_lang(*args, **kwargs):
|
7
|
+
def decorator(func):
|
8
|
+
@functools.wraps(func)
|
9
|
+
def wrapped_func(*args, **kwargs):
|
10
|
+
if len(args) and hasattr(args[0], "request"):
|
11
|
+
request = args[0].request
|
12
|
+
else:
|
13
|
+
request = args[0] if len(args) else kwargs.get("request", None)
|
14
|
+
lang = settings.LANGUAGE_CODE
|
15
|
+
if request and hasattr(request, "GET"):
|
16
|
+
lang = request.GET.get("lang", request.GET.get("language", lang))
|
17
|
+
if request and hasattr(request, "data"):
|
18
|
+
lang = request.data.pop("lang", request.data.pop("language", lang))
|
19
|
+
if lang and lang in [l[0] for l in settings.LANGUAGES]:
|
20
|
+
activate(lang)
|
21
|
+
request.LANGUAGE_CODE = lang
|
22
|
+
return func(*args, **kwargs)
|
23
|
+
|
24
|
+
return wrapped_func
|
25
|
+
|
26
|
+
return decorator
|
@@ -1,13 +1,19 @@
|
|
1
1
|
from django.contrib.contenttypes.models import ContentType
|
2
|
+
from django.db.models import Q
|
2
3
|
from django.http import Http404
|
4
|
+
from django.shortcuts import get_object_or_404
|
3
5
|
from rest_framework.decorators import action
|
4
6
|
from rest_framework.response import Response
|
5
7
|
|
6
8
|
from camomilla.models import AbstractPage, Menu
|
9
|
+
from camomilla.models.page import UrlNode
|
7
10
|
from camomilla.permissions import CamomillaBasePermissions
|
8
11
|
from camomilla.serializers import ContentTypeSerializer, MenuSerializer
|
12
|
+
from camomilla.serializers.page import BasicUrlNodeSerializer
|
9
13
|
from camomilla.views.base import BaseModelViewset
|
14
|
+
from camomilla.views.decorators import active_lang
|
10
15
|
|
16
|
+
from django.utils.translation import get_language
|
11
17
|
|
12
18
|
class MenuViewSet(BaseModelViewset):
|
13
19
|
queryset = Menu.objects.all()
|
@@ -15,6 +21,31 @@ class MenuViewSet(BaseModelViewset):
|
|
15
21
|
permission_classes = (CamomillaBasePermissions,)
|
16
22
|
model = Menu
|
17
23
|
|
24
|
+
lookup_field = "key"
|
25
|
+
|
26
|
+
def get_object(self):
|
27
|
+
queryset = self.filter_queryset(self.get_queryset())
|
28
|
+
lookup_url_kwarg = self.lookup_url_kwarg or self.lookup_field
|
29
|
+
assert lookup_url_kwarg in self.kwargs, (
|
30
|
+
"Expected view %s to be called with a URL keyword argument "
|
31
|
+
'named "%s". Fix your URL conf, or set the `.lookup_field` '
|
32
|
+
"attribute on the view correctly."
|
33
|
+
% (self.__class__.__name__, lookup_url_kwarg)
|
34
|
+
)
|
35
|
+
filter = Q(**{self.lookup_field: self.kwargs[lookup_url_kwarg]})
|
36
|
+
if (
|
37
|
+
isinstance(self.kwargs[lookup_url_kwarg], str)
|
38
|
+
and self.kwargs[lookup_url_kwarg].isnumeric()
|
39
|
+
or isinstance(self.kwargs[lookup_url_kwarg], int)
|
40
|
+
):
|
41
|
+
filter |= Q(pk=self.kwargs[lookup_url_kwarg])
|
42
|
+
|
43
|
+
obj = get_object_or_404(queryset, filter)
|
44
|
+
# May raise a permission denied
|
45
|
+
self.check_object_permissions(self.request, obj)
|
46
|
+
|
47
|
+
return obj
|
48
|
+
|
18
49
|
@action(detail=False, methods=["get"], url_path="page_types")
|
19
50
|
def page_types(self, request, *args, **kwargs):
|
20
51
|
return Response(
|
@@ -42,3 +73,14 @@ class MenuViewSet(BaseModelViewset):
|
|
42
73
|
)
|
43
74
|
]
|
44
75
|
)
|
76
|
+
|
77
|
+
@active_lang()
|
78
|
+
@action(detail=False, methods=["get"], url_path="search_urlnode")
|
79
|
+
def search_urlnode(self, request, *args, **kwargs):
|
80
|
+
url_node = request.GET.get("q", "")
|
81
|
+
qs = UrlNode.objects.filter(permalink__icontains=url_node).order_by("permalink")
|
82
|
+
print(get_language())
|
83
|
+
return Response(BasicUrlNodeSerializer(qs, many=True).data)
|
84
|
+
|
85
|
+
|
86
|
+
|
@@ -0,0 +1,25 @@
|
|
1
|
+
from camomilla.models import Page
|
2
|
+
from camomilla.models.page import UrlNode
|
3
|
+
from camomilla.permissions import CamomillaBasePermissions
|
4
|
+
from camomilla.serializers import PageSerializer
|
5
|
+
from camomilla.serializers.page import UrlNodeSerializer
|
6
|
+
from camomilla.views.base import BaseModelViewset
|
7
|
+
from camomilla.views.decorators import active_lang
|
8
|
+
from camomilla.views.mixins import BulkDeleteMixin, GetUserLanguageMixin
|
9
|
+
from rest_framework.decorators import api_view
|
10
|
+
from rest_framework.response import Response
|
11
|
+
from django.shortcuts import get_object_or_404
|
12
|
+
|
13
|
+
|
14
|
+
class PageViewSet(GetUserLanguageMixin, BulkDeleteMixin, BaseModelViewset):
|
15
|
+
queryset = Page.objects.all()
|
16
|
+
serializer_class = PageSerializer
|
17
|
+
permission_classes = (CamomillaBasePermissions,)
|
18
|
+
model = Page
|
19
|
+
|
20
|
+
|
21
|
+
@active_lang()
|
22
|
+
@api_view(["GET"])
|
23
|
+
def fetch_page(request, permalink=""):
|
24
|
+
node = get_object_or_404(UrlNode, permalink=f"/{permalink}")
|
25
|
+
return Response(UrlNodeSerializer(node, context={"request": request}).data)
|
@@ -1,15 +0,0 @@
|
|
1
|
-
from camomilla.serializers.mixins import AbstractPageMixin
|
2
|
-
from camomilla.models import Content, Page
|
3
|
-
from camomilla.serializers.base import BaseModelSerializer
|
4
|
-
|
5
|
-
|
6
|
-
class ContentSerializer(BaseModelSerializer):
|
7
|
-
class Meta:
|
8
|
-
model = Content
|
9
|
-
fields = "__all__"
|
10
|
-
|
11
|
-
|
12
|
-
class PageSerializer(AbstractPageMixin, BaseModelSerializer):
|
13
|
-
class Meta:
|
14
|
-
model = Page
|
15
|
-
fields = "__all__"
|
@@ -1,30 +0,0 @@
|
|
1
|
-
def build_standard_model_serializer(model, depth, bases=None):
|
2
|
-
if bases is None:
|
3
|
-
from rest_framework.serializers import ModelSerializer
|
4
|
-
from camomilla.serializers.fields import FieldsOverrideMixin
|
5
|
-
from camomilla.serializers.mixins import (
|
6
|
-
JSONFieldPatchMixin,
|
7
|
-
NestMixin,
|
8
|
-
OrderingMixin,
|
9
|
-
SetupEagerLoadingMixin,
|
10
|
-
)
|
11
|
-
|
12
|
-
bases = (
|
13
|
-
NestMixin,
|
14
|
-
FieldsOverrideMixin,
|
15
|
-
JSONFieldPatchMixin,
|
16
|
-
OrderingMixin,
|
17
|
-
SetupEagerLoadingMixin,
|
18
|
-
ModelSerializer,
|
19
|
-
)
|
20
|
-
return type(
|
21
|
-
f"{model.__name__}StandardSerializer",
|
22
|
-
bases,
|
23
|
-
{
|
24
|
-
"Meta": type(
|
25
|
-
"Meta",
|
26
|
-
(object,),
|
27
|
-
{"model": model, "depth": depth, "fields": "__all__"},
|
28
|
-
)
|
29
|
-
},
|
30
|
-
)
|
@@ -1 +0,0 @@
|
|
1
|
-
__version__ = "6.0.0-beta.3"
|
@@ -1,12 +0,0 @@
|
|
1
|
-
from camomilla.models import Page
|
2
|
-
from camomilla.permissions import CamomillaBasePermissions
|
3
|
-
from camomilla.serializers import PageSerializer
|
4
|
-
from camomilla.views.base import BaseModelViewset
|
5
|
-
from camomilla.views.mixins import BulkDeleteMixin, GetUserLanguageMixin
|
6
|
-
|
7
|
-
|
8
|
-
class PageViewSet(GetUserLanguageMixin, BulkDeleteMixin, BaseModelViewset):
|
9
|
-
queryset = Page.objects.all()
|
10
|
-
serializer_class = PageSerializer
|
11
|
-
permission_classes = (CamomillaBasePermissions,)
|
12
|
-
model = Page
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/context_processors.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/dynamic_pages_urls.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/management/__init__.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/models/mixins/__init__.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/serializers/__init__.py
RENAMED
File without changes
|
{django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/serializers/article.py
RENAMED
File without changes
|
{django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/serializers/base/__init__.py
RENAMED
File without changes
|
{django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/serializers/content_type.py
RENAMED
File without changes
|
File without changes
|
{django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/serializers/fields/file.py
RENAMED
File without changes
|
{django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/serializers/fields/json.py
RENAMED
File without changes
|
File without changes
|
{django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/serializers/media.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
{django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/serializers/validators.py
RENAMED
File without changes
|
{django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/storages/__init__.py
RENAMED
File without changes
|
{django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/storages/optimize.py
RENAMED
File without changes
|
{django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/storages/overwrite.py
RENAMED
File without changes
|
{django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/structured/__init__.py
RENAMED
File without changes
|
{django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/structured/fields.py
RENAMED
File without changes
|
{django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/structured/models.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/templates/defaults/base.html
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/templatetags/__init__.py
RENAMED
File without changes
|
File without changes
|
{django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/templatetags/menus.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/utils/normalization.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
{django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/utils/translation.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
{django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/views/base/__init__.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/views/mixins/__init__.py
RENAMED
File without changes
|
{django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/views/mixins/ordering.py
RENAMED
File without changes
|
{django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/views/mixins/pagination.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/tests/test_camomilla_filters.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|