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.
Files changed (114) hide show
  1. {django-camomilla-cms-6.0.0b3/django_camomilla_cms.egg-info → django-camomilla-cms-6.0.0b4}/PKG-INFO +1 -1
  2. {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/__init__.py +1 -1
  3. {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/contrib/rest_framework/serializer.py +30 -0
  4. {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/models/page.py +18 -7
  5. {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/serializers/mixins/__init__.py +16 -0
  6. django-camomilla-cms-6.0.0b4/camomilla/serializers/page.py +63 -0
  7. django-camomilla-cms-6.0.0b4/camomilla/serializers/utils.py +35 -0
  8. {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/settings.py +7 -0
  9. {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/structured/cache.py +3 -0
  10. django-camomilla-cms-6.0.0b4/camomilla/theme/__init__.py +1 -0
  11. {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/urls.py +3 -0
  12. django-camomilla-cms-6.0.0b4/camomilla/views/decorators.py +26 -0
  13. {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/views/menus.py +42 -0
  14. django-camomilla-cms-6.0.0b4/camomilla/views/pages.py +25 -0
  15. {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4/django_camomilla_cms.egg-info}/PKG-INFO +1 -1
  16. {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/django_camomilla_cms.egg-info/SOURCES.txt +1 -0
  17. {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/setup.py +1 -1
  18. django-camomilla-cms-6.0.0b3/camomilla/serializers/page.py +0 -15
  19. django-camomilla-cms-6.0.0b3/camomilla/serializers/utils.py +0 -30
  20. django-camomilla-cms-6.0.0b3/camomilla/theme/__init__.py +0 -1
  21. django-camomilla-cms-6.0.0b3/camomilla/views/pages.py +0 -12
  22. {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/LICENSE +0 -0
  23. {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/MANIFEST.in +0 -0
  24. {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/README.md +0 -0
  25. {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/apps.py +0 -0
  26. {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/authentication.py +0 -0
  27. {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/context_processors.py +0 -0
  28. {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/contrib/__init__.py +0 -0
  29. {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/contrib/modeltranslation/__init__.py +0 -0
  30. {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/contrib/modeltranslation/hvad_migration.py +0 -0
  31. {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/contrib/rest_framework/__init__.py +0 -0
  32. {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/defaults.py +0 -0
  33. {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/dynamic_pages_urls.py +0 -0
  34. {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/exceptions.py +0 -0
  35. {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/fields/__init__.py +0 -0
  36. {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/fields/json.py +0 -0
  37. {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/management/__init__.py +0 -0
  38. {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/management/commands/__init__.py +0 -0
  39. {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/management/commands/regenerate_thumbnails.py +0 -0
  40. {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/model_api.py +0 -0
  41. {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/models/__init__.py +0 -0
  42. {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/models/article.py +0 -0
  43. {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/models/content.py +0 -0
  44. {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/models/media.py +0 -0
  45. {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/models/menu.py +0 -0
  46. {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/models/mixins/__init__.py +0 -0
  47. {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/openapi/__init__.py +0 -0
  48. {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/openapi/schema.py +0 -0
  49. {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/parsers.py +0 -0
  50. {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/permissions.py +0 -0
  51. {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/serializers/__init__.py +0 -0
  52. {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/serializers/article.py +0 -0
  53. {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/serializers/base/__init__.py +0 -0
  54. {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/serializers/content_type.py +0 -0
  55. {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/serializers/fields/__init__.py +0 -0
  56. {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/serializers/fields/file.py +0 -0
  57. {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/serializers/fields/json.py +0 -0
  58. {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/serializers/fields/related.py +0 -0
  59. {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/serializers/media.py +0 -0
  60. {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/serializers/menu.py +0 -0
  61. {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/serializers/user.py +0 -0
  62. {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/serializers/validators.py +0 -0
  63. {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/storages/__init__.py +0 -0
  64. {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/storages/optimize.py +0 -0
  65. {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/storages/overwrite.py +0 -0
  66. {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/structured/__init__.py +0 -0
  67. {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/structured/fields.py +0 -0
  68. {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/structured/models.py +0 -0
  69. {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/structured/utils.py +0 -0
  70. {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/templates/admin/camomilla/page/change_form.html +0 -0
  71. {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/templates/defaults/articles/default.html +0 -0
  72. {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/templates/defaults/base.html +0 -0
  73. {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/templates/defaults/pages/default.html +0 -0
  74. {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/templates/defaults/parts/langswitch.html +0 -0
  75. {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/templates/defaults/parts/menu.html +0 -0
  76. {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/templates/defaults/widgets/media_select_multiple.html +0 -0
  77. {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/templatetags/__init__.py +0 -0
  78. {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/templatetags/camomilla_filters.py +0 -0
  79. {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/templatetags/menus.py +0 -0
  80. {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/theme/admin.py +0 -0
  81. {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/theme/apps.py +0 -0
  82. {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/theme/static/admin/css/responsive.css +0 -0
  83. {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/theme/static/admin/img/favicon.ico +0 -0
  84. {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/theme/static/admin/img/logo.svg +0 -0
  85. {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/theme/templates/admin/base.html +0 -0
  86. {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/theme/templates/rosetta/base.html +0 -0
  87. {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/translation.py +0 -0
  88. {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/utils/__init__.py +0 -0
  89. {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/utils/getters.py +0 -0
  90. {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/utils/normalization.py +0 -0
  91. {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/utils/seo.py +0 -0
  92. {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/utils/templates.py +0 -0
  93. {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/utils/translation.py +0 -0
  94. {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/views/__init__.py +0 -0
  95. {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/views/articles.py +0 -0
  96. {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/views/base/__init__.py +0 -0
  97. {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/views/contents.py +0 -0
  98. {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/views/languages.py +0 -0
  99. {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/views/medias.py +0 -0
  100. {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/views/mixins/__init__.py +0 -0
  101. {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/views/mixins/ordering.py +0 -0
  102. {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/views/mixins/pagination.py +0 -0
  103. {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/views/tags.py +0 -0
  104. {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/camomilla/views/users.py +0 -0
  105. {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/django_camomilla_cms.egg-info/dependency_links.txt +0 -0
  106. {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/django_camomilla_cms.egg-info/requires.txt +0 -0
  107. {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/django_camomilla_cms.egg-info/top_level.txt +0 -0
  108. {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/setup.cfg +0 -0
  109. {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/tests/__init__.py +0 -0
  110. {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/tests/test_api.py +0 -0
  111. {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/tests/test_camomilla_filters.py +0 -0
  112. {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/tests/test_models.py +0 -0
  113. {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/tests/test_utils.py +0 -0
  114. {django-camomilla-cms-6.0.0b3 → django-camomilla-cms-6.0.0b4}/tests/urls.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: django-camomilla-cms
3
- Version: 6.0.0b3
3
+ Version: 6.0.0b4
4
4
  Summary: Django powered cms
5
5
  Home-page: https://github.com/lotrekagency/camomilla
6
6
  Author: Lotrèk
@@ -1,4 +1,4 @@
1
- __version__ = "6.0.0-beta.3"
1
+ __version__ = "6.0.0-beta.4"
2
2
 
3
3
 
4
4
  def get_core_apps():
@@ -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
- @property
102
- def routerlink(self) -> str:
101
+ @staticmethod
102
+ def reverse_url(permalink: str) -> str:
103
103
  try:
104
- if self.permalink == "/":
104
+ if permalink == "/":
105
105
  return reverse("camomilla-homepage")
106
- return reverse("camomilla-permalink", args=(self.permalink.lstrip("/"),))
106
+ return reverse("camomilla-permalink", args=(permalink.lstrip("/"),))
107
107
  except NoReverseMatch:
108
- return self.permalink
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 = "Match found: %s.\nThe page appears not to be public.\nUse ?preview=true in the url to see it." % page
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
- return get_field_translations(self.url_node or object, "permalink", None)
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,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: django-camomilla-cms
3
- Version: 6.0.0b3
3
+ Version: 6.0.0b4
4
4
  Summary: Django powered cms
5
5
  Home-page: https://github.com/lotrekagency/camomilla
6
6
  Author: Lotrèk
@@ -85,6 +85,7 @@ camomilla/utils/translation.py
85
85
  camomilla/views/__init__.py
86
86
  camomilla/views/articles.py
87
87
  camomilla/views/contents.py
88
+ camomilla/views/decorators.py
88
89
  camomilla/views/languages.py
89
90
  camomilla/views/medias.py
90
91
  camomilla/views/menus.py
@@ -1,5 +1,5 @@
1
1
  from setuptools import setup
2
2
 
3
- __version__ = "6.0.0-beta.3"
3
+ __version__ = "6.0.0-beta.4"
4
4
 
5
5
  setup(version=__version__)
@@ -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