django-camomilla-cms 5.8.5__py2.py3-none-any.whl → 6.0.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.
Files changed (143) hide show
  1. camomilla/__init__.py +8 -2
  2. camomilla/apps.py +9 -1
  3. camomilla/context_processors.py +6 -0
  4. camomilla/contrib/modeltranslation/__init__.py +0 -0
  5. camomilla/contrib/modeltranslation/hvad_migration.py +126 -0
  6. camomilla/dynamic_pages_urls.py +33 -0
  7. camomilla/fields/__init__.py +13 -0
  8. camomilla/{fields.py → fields/json.py} +15 -18
  9. camomilla/management/commands/regenerate_thumbnails.py +0 -1
  10. camomilla/managers/__init__.py +3 -0
  11. camomilla/managers/pages.py +116 -0
  12. camomilla/model_api.py +86 -0
  13. camomilla/models/__init__.py +5 -6
  14. camomilla/models/article.py +26 -44
  15. camomilla/models/content.py +8 -15
  16. camomilla/models/media.py +70 -97
  17. camomilla/models/menu.py +106 -0
  18. camomilla/models/mixins/__init__.py +10 -48
  19. camomilla/models/page.py +521 -20
  20. camomilla/openapi/__init__.py +0 -0
  21. camomilla/openapi/schema.py +67 -0
  22. camomilla/parsers.py +0 -1
  23. camomilla/redirects.py +10 -0
  24. camomilla/serializers/__init__.py +2 -0
  25. camomilla/serializers/article.py +5 -10
  26. camomilla/serializers/base/__init__.py +21 -17
  27. camomilla/serializers/content_type.py +17 -0
  28. camomilla/serializers/fields/__init__.py +6 -20
  29. camomilla/serializers/fields/file.py +5 -0
  30. camomilla/serializers/fields/related.py +24 -4
  31. camomilla/serializers/media.py +6 -8
  32. camomilla/serializers/menu.py +17 -0
  33. camomilla/serializers/mixins/__init__.py +23 -187
  34. camomilla/serializers/mixins/fields.py +20 -0
  35. camomilla/serializers/mixins/filter_fields.py +57 -0
  36. camomilla/serializers/mixins/json.py +34 -0
  37. camomilla/serializers/mixins/language.py +32 -0
  38. camomilla/serializers/mixins/nesting.py +35 -0
  39. camomilla/serializers/mixins/optimize.py +91 -0
  40. camomilla/serializers/mixins/ordering.py +34 -0
  41. camomilla/serializers/mixins/page.py +58 -0
  42. camomilla/serializers/mixins/translation.py +103 -0
  43. camomilla/serializers/page.py +53 -4
  44. camomilla/serializers/user.py +5 -4
  45. camomilla/serializers/utils.py +38 -0
  46. camomilla/serializers/validators.py +51 -0
  47. camomilla/settings.py +118 -0
  48. camomilla/sitemap.py +30 -0
  49. camomilla/storages/__init__.py +4 -0
  50. camomilla/storages/default.py +12 -0
  51. camomilla/storages/optimize.py +71 -0
  52. camomilla/{storages.py → storages/overwrite.py} +2 -2
  53. camomilla/templates/admin/camomilla/page/change_form.html +10 -0
  54. camomilla/templates/defaults/articles/default.html +7 -0
  55. camomilla/templates/defaults/base.html +170 -0
  56. camomilla/templates/defaults/pages/default.html +3 -0
  57. camomilla/templates/defaults/parts/langswitch.html +83 -0
  58. camomilla/templates/defaults/parts/menu.html +15 -0
  59. camomilla/templates_context/__init__.py +0 -0
  60. camomilla/templates_context/autodiscover.py +51 -0
  61. camomilla/templates_context/rendering.py +89 -0
  62. camomilla/templatetags/camomilla_filters.py +6 -5
  63. camomilla/templatetags/menus.py +37 -0
  64. camomilla/templatetags/model_extras.py +77 -0
  65. camomilla/theme/__init__.py +1 -1
  66. camomilla/theme/admin/__init__.py +99 -0
  67. camomilla/theme/admin/pages.py +46 -0
  68. camomilla/theme/admin/translations.py +13 -0
  69. camomilla/theme/apps.py +38 -0
  70. camomilla/theme/static/admin/css/responsive.css +5 -1021
  71. camomilla/theme/static/admin/img/favicon.ico +0 -0
  72. camomilla/theme/static/admin/img/logo.svg +31 -0
  73. camomilla/theme/templates/admin/base.html +7 -0
  74. camomilla/theme/templates/rosetta/base.html +196 -0
  75. camomilla/translation.py +61 -0
  76. camomilla/urls.py +38 -17
  77. camomilla/utils/__init__.py +4 -0
  78. camomilla/utils/getters.py +27 -0
  79. camomilla/utils/normalization.py +7 -0
  80. camomilla/utils/query_parser.py +167 -0
  81. camomilla/{utils.py → utils/seo.py} +13 -15
  82. camomilla/utils/setters.py +37 -0
  83. camomilla/utils/templates.py +32 -0
  84. camomilla/utils/translation.py +114 -0
  85. camomilla/views/__init__.py +1 -1
  86. camomilla/views/articles.py +5 -7
  87. camomilla/views/base/__init__.py +35 -5
  88. camomilla/views/contents.py +6 -11
  89. camomilla/views/decorators.py +26 -0
  90. camomilla/views/medias.py +24 -19
  91. camomilla/views/menus.py +81 -0
  92. camomilla/views/mixins/__init__.py +17 -73
  93. camomilla/views/mixins/bulk_actions.py +22 -0
  94. camomilla/views/mixins/language.py +33 -0
  95. camomilla/views/mixins/optimize.py +18 -0
  96. camomilla/views/mixins/ordering.py +2 -2
  97. camomilla/views/mixins/pagination.py +12 -18
  98. camomilla/views/mixins/permissions.py +6 -0
  99. camomilla/views/pages.py +28 -6
  100. camomilla/views/tags.py +5 -6
  101. camomilla/views/users.py +7 -12
  102. django_camomilla_cms-6.0.0.dist-info/METADATA +123 -0
  103. django_camomilla_cms-6.0.0.dist-info/RECORD +133 -0
  104. {django_camomilla_cms-5.8.5.dist-info → django_camomilla_cms-6.0.0.dist-info}/WHEEL +1 -1
  105. tests/fixtures/__init__.py +14 -0
  106. tests/test_api.py +22 -39
  107. tests/test_camomilla_filters.py +11 -13
  108. tests/test_media.py +152 -0
  109. tests/test_menu.py +112 -0
  110. tests/test_model_api.py +113 -0
  111. tests/test_model_api_permissions.py +44 -0
  112. tests/test_model_api_register.py +355 -0
  113. tests/test_pages.py +351 -0
  114. tests/test_query_parser.py +58 -0
  115. tests/test_templates_context.py +149 -0
  116. tests/test_utils.py +64 -64
  117. tests/utils/__init__.py +0 -0
  118. tests/utils/api.py +28 -0
  119. tests/utils/media.py +10 -0
  120. camomilla/admin.py +0 -98
  121. camomilla/migrations/0001_initial.py +0 -577
  122. camomilla/migrations/0002_auto_20200214_1127.py +0 -33
  123. camomilla/migrations/0003_auto_20210130_1610.py +0 -30
  124. camomilla/migrations/0004_auto_20210511_0937.py +0 -25
  125. camomilla/migrations/0005_media_image_props.py +0 -19
  126. camomilla/migrations/0006_auto_20220103_1845.py +0 -35
  127. camomilla/migrations/0007_auto_20220211_1622.py +0 -18
  128. camomilla/migrations/0008_auto_20220309_1616.py +0 -60
  129. camomilla/migrations/0009_article__hvad_query_category__hvad_query_and_more.py +0 -165
  130. camomilla/migrations/0010_auto_20220802_1406.py +0 -83
  131. camomilla/migrations/0011_auto_20220902_1000.py +0 -15
  132. camomilla/models/category.py +0 -25
  133. camomilla/models/tag.py +0 -19
  134. camomilla/theme/static/admin/img/logo.png +0 -0
  135. camomilla/theme/templates/admin/base_site.html +0 -18
  136. camomilla/views/categories.py +0 -13
  137. django_camomilla_cms-5.8.5.dist-info/METADATA +0 -62
  138. django_camomilla_cms-5.8.5.dist-info/RECORD +0 -76
  139. tests/urls.py +0 -21
  140. /camomilla/{migrations → contrib}/__init__.py +0 -0
  141. /camomilla/templates/{camomilla → defaults}/widgets/media_select_multiple.html +0 -0
  142. {django_camomilla_cms-5.8.5.dist-info → django_camomilla_cms-6.0.0.dist-info/licenses}/LICENSE +0 -0
  143. {django_camomilla_cms-5.8.5.dist-info → django_camomilla_cms-6.0.0.dist-info}/top_level.txt +0 -0
@@ -2,6 +2,8 @@ from rest_framework.response import Response
2
2
  from django.db.models import Q
3
3
  from django.core.paginator import EmptyPage, PageNotAnInteger, Paginator
4
4
  from django.contrib.postgres.search import SearchVector, SearchQuery, TrigramSimilarity
5
+ from camomilla.utils.query_parser import ConditionParser
6
+ from django.conf import settings
5
7
 
6
8
 
7
9
  class TrigramSearchMixin:
@@ -32,19 +34,6 @@ class PaginateStackMixin:
32
34
  list_handler, "shared_model", getattr(list_handler, "model", None)
33
35
  )
34
36
 
35
- def parse_qs_value(self, string: str):
36
- if string and string.startswith("[") and string.endswith("]"):
37
- string = [self.parse_qs_value(substr) for substr in string[1:-1].split(",")]
38
- elif string and string.lower() in ["true", "false"]:
39
- string = string.lower() == "true"
40
- elif string and string.isdigit():
41
- string = int(string)
42
- return string
43
-
44
- def parse_filter(self, filter):
45
- filter_name, value = filter.split("=")
46
- return filter_name, self.parse_qs_value(value)
47
-
48
37
  def handle_pagination(self, list_handler=None, items_per_page=None):
49
38
  list_handler = list_handler if list_handler is not None else self.get_queryset()
50
39
  items_per_page = int(
@@ -84,8 +73,7 @@ class PaginateStackMixin:
84
73
  filters = dict(self.request.GET).get("fltr", [])
85
74
  for filter in filters:
86
75
  try:
87
- filter_name, value = self.parse_filter(filter)
88
- list_handler = list_handler.filter(**{filter_name: value})
76
+ list_handler = list_handler.filter(ConditionParser(filter).db_query)
89
77
  except Exception:
90
78
  pass
91
79
  return list_handler
@@ -95,9 +83,15 @@ class PaginateStackMixin:
95
83
  search_string = self.request.GET.get("search", None)
96
84
  search_fields = search_fields or getattr(self, "search_fields", [])
97
85
  if search_string and len(search_fields) > 0:
98
- return list_handler.annotate(
99
- search=SearchVector(*search_fields),
100
- ).filter(search=SearchQuery(search_string))
86
+ if "sqlite" in settings.DATABASES["default"]["ENGINE"]:
87
+ filter_statement = Q()
88
+ for field in search_fields:
89
+ filter_statement |= Q(**{field + "__icontains": search_string})
90
+ return list_handler.filter(filter_statement)
91
+ else:
92
+ return list_handler.annotate(
93
+ search=SearchVector(*search_fields),
94
+ ).filter(search=SearchQuery(search_string))
101
95
 
102
96
  return list_handler
103
97
 
@@ -0,0 +1,6 @@
1
+ from camomilla.permissions import CamomillaBasePermissions
2
+
3
+
4
+ class CamomillaBasePermissionMixin:
5
+ def get_permissions(self):
6
+ return [*super().get_permissions(), CamomillaBasePermissions()]
camomilla/views/pages.py CHANGED
@@ -1,13 +1,35 @@
1
- from .base import BaseModelViewset
2
- from .mixins import GetUserLanguageMixin, BulkDeleteMixin
3
- from ..models import Page
4
- from ..serializers import PageSerializer
5
- from ..permissions import CamomillaBasePermissions
1
+ from camomilla.models import Page
2
+ from camomilla.models.page import UrlNode, UrlRedirect
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, permission_classes
10
+ from rest_framework.response import Response
11
+ from rest_framework import permissions
12
+ from django.shortcuts import get_object_or_404
6
13
 
7
14
 
8
15
  class PageViewSet(GetUserLanguageMixin, BulkDeleteMixin, BaseModelViewset):
9
-
10
16
  queryset = Page.objects.all()
11
17
  serializer_class = PageSerializer
12
18
  permission_classes = (CamomillaBasePermissions,)
13
19
  model = Page
20
+
21
+
22
+ @active_lang()
23
+ @api_view(["GET"])
24
+ @permission_classes(
25
+ [
26
+ permissions.AllowAny,
27
+ ]
28
+ )
29
+ def fetch_page(request, permalink=""):
30
+ redirect = UrlRedirect.find_redirect_from_url(f"/{permalink}")
31
+ if redirect:
32
+ redirect = redirect.redirect()
33
+ return Response({"redirect": redirect.url, "status": redirect.status_code})
34
+ node = get_object_or_404(UrlNode, permalink=f"/{permalink}")
35
+ return Response(UrlNodeSerializer(node, context={"request": request}).data)
camomilla/views/tags.py CHANGED
@@ -1,12 +1,11 @@
1
- from .base import BaseModelViewset
2
- from .mixins import GetUserLanguageMixin, BulkDeleteMixin
3
- from ..models import Tag
4
- from ..serializers import TagSerializer
5
- from ..permissions import CamomillaBasePermissions
1
+ from camomilla.models import Tag
2
+ from camomilla.permissions import CamomillaBasePermissions
3
+ from camomilla.serializers import TagSerializer
4
+ from camomilla.views.base import BaseModelViewset
5
+ from camomilla.views.mixins import BulkDeleteMixin, GetUserLanguageMixin
6
6
 
7
7
 
8
8
  class TagViewSet(GetUserLanguageMixin, BulkDeleteMixin, BaseModelViewset):
9
-
10
9
  queryset = Tag.objects.all()
11
10
  serializer_class = TagSerializer
12
11
  permission_classes = (CamomillaBasePermissions,)
camomilla/views/users.py CHANGED
@@ -1,23 +1,20 @@
1
- from .base import BaseModelViewset
2
- from django.contrib.auth import get_user_model
1
+ from django.contrib.auth import get_user_model, login, logout
3
2
  from django.contrib.auth.models import Permission
4
-
5
3
  from django.db.models import Q
6
-
7
4
  from rest_framework.authtoken.models import Token
8
- from rest_framework.response import Response
9
5
  from rest_framework.authtoken.views import ObtainAuthToken
10
6
  from rest_framework.decorators import action
11
7
  from rest_framework.permissions import IsAuthenticated
8
+ from rest_framework.response import Response
9
+ from rest_framework.views import APIView
12
10
 
13
- from ..serializers import (
11
+ from camomilla.permissions import CamomillaBasePermissions, CamomillaSuperUser, ReadOnly
12
+ from camomilla.serializers import (
13
+ PermissionSerializer,
14
14
  UserProfileSerializer,
15
15
  UserSerializer,
16
- PermissionSerializer,
17
16
  )
18
- from ..permissions import CamomillaSuperUser, CamomillaBasePermissions, ReadOnly
19
- from django.contrib.auth import login, logout
20
- from rest_framework.views import APIView
17
+ from camomilla.views.base import BaseModelViewset
21
18
 
22
19
 
23
20
  class CamomillaObtainAuthToken(ObtainAuthToken):
@@ -30,7 +27,6 @@ class CamomillaObtainAuthToken(ObtainAuthToken):
30
27
 
31
28
 
32
29
  class UserViewSet(BaseModelViewset):
33
-
34
30
  queryset = get_user_model().objects.all()
35
31
  serializer_class = UserSerializer
36
32
  model = get_user_model()
@@ -58,7 +54,6 @@ class UserViewSet(BaseModelViewset):
58
54
 
59
55
 
60
56
  class PermissionViewSet(BaseModelViewset):
61
-
62
57
  queryset = Permission.objects.all()
63
58
  serializer_class = PermissionSerializer
64
59
  model = Permission
@@ -0,0 +1,123 @@
1
+ Metadata-Version: 2.4
2
+ Name: django-camomilla-cms
3
+ Version: 6.0.0
4
+ Summary: Django powered cms
5
+ Author-email: Lotrèk <dimmitutto@lotrek.it>
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/camomillacms/camomilla-core
8
+ Keywords: cms,django,api cms
9
+ Classifier: Environment :: Web Environment
10
+ Classifier: Framework :: Django
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: Programming Language :: Python
13
+ Classifier: Programming Language :: Python :: 3
14
+ Requires-Python: <=3.13,>=3.8
15
+ Description-Content-Type: text/markdown
16
+ License-File: LICENSE
17
+ Requires-Dist: django-modeltranslation<=0.18.12,>=0.18.7
18
+ Requires-Dist: djsuperadmin<1.0.0,>=0.9
19
+ Requires-Dist: djangorestframework<=3.14.0,>=3.10.0
20
+ Requires-Dist: django-structured-json-field>=0.4.2
21
+ Requires-Dist: Pillow>=10.0.0
22
+ Requires-Dist: django-admin-interface<1.0.0,>=0.26.0
23
+ Requires-Dist: django-ckeditor<7.0.0,>=5.7.1
24
+ Requires-Dist: django-tinymce<5.0.0,>=4.1.0
25
+ Requires-Dist: python-magic<0.5,>=0.4
26
+ Requires-Dist: Django<6,>=3.2
27
+ Requires-Dist: django_jsonform>=2.23
28
+ Dynamic: license-file
29
+
30
+ [![PyPI](https://img.shields.io/pypi/v/django-camomilla-cms?style=flat-square)](https://pypi.org/project/django-camomilla-cms) ![Codecov](https://img.shields.io/codecov/c/github/camomillacms/camomilla-core?style=flat-square) [![License](https://img.shields.io/github/license/camomillacms/camomilla-core?style=flat-square)](./LICENSE)
31
+
32
+ <br>
33
+ <br>
34
+ <br>
35
+ <br>
36
+ <div align="center">
37
+ <picture>
38
+ <source media="(prefers-color-scheme: dark)" srcset="https://camomillacms.github.io/camomilla-core/images/camomilla-logo-dark.svg?v=1">
39
+ <source media="(prefers-color-scheme: light)" srcset="https://camomillacms.github.io/camomilla-core/images/camomilla-logo-light.svg?v=1">
40
+ <img alt="Fallback image description" src="https://camomillacms.github.io/camomilla-core/images/camomilla-logo-light.svg?v=1" style="width: 250px; height: auto;">
41
+ </picture>
42
+ </div>
43
+ <h3 align="center"">Our beloved Django CMS</h3>
44
+ <br>
45
+
46
+ ## ⭐️ Features
47
+
48
+ <!-- Highlight some of the features your module provide here -->
49
+
50
+ - 🧘‍♀️ &nbsp;Built on top of the django framework
51
+ - 🥨 &nbsp;Beaked page abstract model to let you manage everything you need as a page.
52
+ - 🏞️ &nbsp;Optimized media management with autoresize
53
+ - 👯 &nbsp;Enable relations inside django JSONFields
54
+ - ⚡️ &nbsp;AutoCreate api endpoints from models
55
+ - 🚧 &nbsp;Enable JsonSchema directly in models endpoints
56
+
57
+ Camomilla is a Django CMS that allows you to create and manage your website's content with ease. It provides a simple and intuitive interface for managing pages, media, and other content types. Camomilla is built on top of the Django framework, which means it inherits all the features and benefits of Django framework.
58
+ We try to continuously improve Camomilla by adding new features and fixing bugs. You can check the [CHANGELOG](./CHANGELOG.md) to see what has been added in the latest releases.
59
+
60
+ ## 📦 Quick Start
61
+
62
+ Here you can find some quick setup instructions to get started with Camomilla. For more detailed information, please refer to the [documentation](https://camomillacms.github.io/camomilla-core/).
63
+
64
+ > [!TIP]
65
+ >
66
+ > #### Env Virtualization 👾
67
+ >
68
+ > Use a virtualenv to isolate your project's dependencies from the system's python installation before starting. Check out [virtualenvwrapper](https://virtualenvwrapper.readthedocs.io/en/latest/) for more information.
69
+
70
+ Install django-camomilla-cms and django from pip
71
+
72
+ ```bash
73
+ $ pip install django
74
+ $ pip install django-camomilla-cms==6.0.0
75
+ ```
76
+
77
+ Create a new django project
78
+
79
+ ```bash
80
+ $ django-admin startproject <project_name>
81
+ $ cd <project_name>
82
+ ```
83
+
84
+ Create a dedicated folder for camomilla migrations
85
+
86
+ ```bash
87
+ $ mkdir -p camomilla_migrations
88
+ $ touch camomilla_migrations.__init__.py
89
+ ```
90
+
91
+ Create migrations and prepare the database
92
+
93
+ ```bash
94
+ $ python manage.py makemigrations camomilla
95
+ $ python manage.py migrate
96
+ ```
97
+
98
+ Add camomilla and camomilla dependencies to your project's INSTALLED_APPS
99
+
100
+ ```python
101
+ # <project_name>/settings.py
102
+
103
+ INSTALLED_APPS = [
104
+ ...
105
+ 'camomilla', # always needed
106
+ 'camomilla.theme', # needed to customize admin interface
107
+ 'djsuperadmin', # needed if you whant to use djsuperadmin for contents
108
+ 'modeltranslation', # needed if your website is multilanguage (can be added later)
109
+ 'rest_framework', # always needed
110
+ 'rest_framework.authtoken', # always needed
111
+ ...
112
+ ]
113
+ ```
114
+
115
+ Run the server
116
+
117
+ ```bash
118
+ $ python manage.py runserver
119
+ ```
120
+
121
+ ## 🧑‍💻 How to Contribute
122
+
123
+ We welcome contributions to Camomilla! If you want to contribute, please read our [contributing guide](./CONTRIBUTING.md) for more information on how to get started.
@@ -0,0 +1,133 @@
1
+ camomilla/__init__.py,sha256=T4RQh9h9WLErkx39DpkEvVOZGAfcYxnIlrNV27pjTdk,243
2
+ camomilla/apps.py,sha256=eUwb9ynyiRAc5OXgt7ZsAdhsCOnPCpNdIFYMheNeN-o,532
3
+ camomilla/authentication.py,sha256=jz6tQT4PPEu-_JLox1LZrOy7EiWBb9MWaObK63MJGus,855
4
+ camomilla/context_processors.py,sha256=cGowjDZ-oDGYn1j2Pj5QDGCqnzXAOdOwp5dmzin_FTc,165
5
+ camomilla/defaults.py,sha256=VNQ_sbxu09AyFGNpUUYypIAyhlBhEORD36BBNj7e73I,1220
6
+ camomilla/dynamic_pages_urls.py,sha256=wd52ktpY_LH24jTW77vII7XZ25p_Kz5MSjes8s_94-A,1278
7
+ camomilla/exceptions.py,sha256=gLniAsK_pmsNNKGMv5Z384LXVbM8oeHcOwz4F91u1LY,111
8
+ camomilla/model_api.py,sha256=-7l3fc2eN1itCMzkWA8nFaQXMmz0vs7IlGlShF-gSuo,2487
9
+ camomilla/parsers.py,sha256=fL8XGCGPxJIZNZkPdGtnPSbDP-6-yzGOCVMuLPjkx9Y,1975
10
+ camomilla/permissions.py,sha256=9NlBO4JMmg36vXCUjPNyq6uZxhkdrnXyIbJVLtWhGWE,1813
11
+ camomilla/redirects.py,sha256=ilcyHidb5Iw3jTrXMnPntr50kkl_WB3QOB0VNkIxP7A,263
12
+ camomilla/settings.py,sha256=JZ5AH0RKOp35xaFUfZ04EMtyr3DQNwOx2M9TndS0NLI,3759
13
+ camomilla/sitemap.py,sha256=U2t5TwhB_-sEscmQZ69PZ5st3bIap8NRxzWEvCgB130,786
14
+ camomilla/translation.py,sha256=_QyfTlKG6hQ_ClRfxzeJ-3oI3Nu5peJN9xFkO9Ib3As,1316
15
+ camomilla/urls.py,sha256=XgaeFoG2eXlJQve3KmFKlD-74CMLW1ziaY1mq-lrAiA,2095
16
+ camomilla/contrib/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
17
+ camomilla/contrib/modeltranslation/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
18
+ camomilla/contrib/modeltranslation/hvad_migration.py,sha256=3j_q_Q85eF4iHbU4LG1Zr3LOmfmGmFiVSL-C8KvPsJQ,5409
19
+ camomilla/fields/__init__.py,sha256=gKrJwHvUA3q_wu-OVV0hrRZmFkT4znMHrmZtpriDumw,323
20
+ camomilla/fields/json.py,sha256=tWEDn6kwTP6pNB53djxuVPu2d57m9cIDc4ccCEfUbDQ,1938
21
+ camomilla/management/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
22
+ camomilla/management/commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
23
+ camomilla/management/commands/regenerate_thumbnails.py,sha256=pKToASR8p8TJezGpFfuylsAHtriNueJ7xqJJxq55adY,496
24
+ camomilla/managers/__init__.py,sha256=Zwp28E1RKafIl0FqcUi1YNHxF19IsMIvhlhS-Njg9Mw,60
25
+ camomilla/managers/pages.py,sha256=DYV1i5vPgxn1YzJlY3kSlsVCRgsiojLxjs2O0LylxEI,3925
26
+ camomilla/models/__init__.py,sha256=y7Q34AGhQ1weJUKWb6XjiyUbwRnJeylOBGMErU0wqYg,147
27
+ camomilla/models/article.py,sha256=LgkZgRsubtDV6NwBz8E2bIgKD6H3I-1QLAxEan5TYYs,1139
28
+ camomilla/models/content.py,sha256=mIgtifb_WMIt58we5u6qWZemHvuDN1zZaBeCyzHL78A,956
29
+ camomilla/models/media.py,sha256=pD-qldiHDOOHgux4lsivQLBcOJJrRx3a4Bg8ODNx7r0,6852
30
+ camomilla/models/menu.py,sha256=hUszPcn1prWCDhk4RPvbITmyhsB2CjFkaerx9t1GWnc,3766
31
+ camomilla/models/page.py,sha256=lkZPdPkl8Yxpz_NfYrpr7Myp8hB3bEAGtdJwKBR7_cg,19385
32
+ camomilla/models/mixins/__init__.py,sha256=c2NixqvrIX4E9WGRqQbylXlqBWDXEqN9mzs_dpB0hFQ,1248
33
+ camomilla/openapi/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
34
+ camomilla/openapi/schema.py,sha256=C22dhKjaJ2DTK4KWFjyMJXiwe8NLy7ZTW5d-I1dqZ7g,2546
35
+ camomilla/serializers/__init__.py,sha256=8v1GsJ_YZ6T72VnKBb5l-8K93oaLf4PIsMt-yFtK-Gk,176
36
+ camomilla/serializers/article.py,sha256=pYVcS0KztzjzSqgruElQMMEZcqTzmQUqXrdv_Sx5Az4,401
37
+ camomilla/serializers/content_type.py,sha256=qB2wkmkvQI6LHxfSI6auEh6M9cJRFBaHnpmkBCCzeYo,557
38
+ camomilla/serializers/media.py,sha256=H4JVpRVxXVmn_BiqrjihKXpfLm9fLmHDFIICRDGJU4s,1940
39
+ camomilla/serializers/menu.py,sha256=TdoyXs40PqxNevnRbBbYOOX9rUv9zQGiHFNduspaZnw,552
40
+ camomilla/serializers/page.py,sha256=NNjEypVYu_9iKqdHV_-61ea37gxiHlDP5gsloV_i6yg,1834
41
+ camomilla/serializers/user.py,sha256=CzrHiVRvYYWNE4eNpCNKtJB7DjVqHHwIcP4NUBXMHSo,3706
42
+ camomilla/serializers/utils.py,sha256=XRL4CNwQDBNpX8xT7365Dw2Cyx8Kvh18GaadgjS9awk,968
43
+ camomilla/serializers/validators.py,sha256=X2uBlh348nJjUWHPtiu9XKCD7Etsdg0811a4xHLAUzU,2103
44
+ camomilla/serializers/base/__init__.py,sha256=maaL3y6tvc5Ph9y07KVcMvZVYTkzh_3aBiBnGCoi1EA,799
45
+ camomilla/serializers/fields/__init__.py,sha256=0I_E9oMtlC0H48LjStMQZiZ-Ycoy49nWK9GvA5JWxN8,145
46
+ camomilla/serializers/fields/file.py,sha256=yjKMho2ti9TIAzo6nwyLnNPJ6GVUumL2wxhegvYqI2o,800
47
+ camomilla/serializers/fields/related.py,sha256=qQQeUxIZSNqnVRHsXocLGmBNHjAvrlr0eDY9K2uCjWk,5069
48
+ camomilla/serializers/mixins/__init__.py,sha256=gMyFpSWHLtLTlKucP1Xk-GtBNX48CwwyY6_wEN3L9vA,640
49
+ camomilla/serializers/mixins/fields.py,sha256=h-YBHBITLGHsrXRgSYP3NBoUzJqmQ_5HhhftoFFNsKs,711
50
+ camomilla/serializers/mixins/filter_fields.py,sha256=sqnCG1hi_qfISFJvwgh37BLyQoNDifR0pU7zmJn_MW8,2236
51
+ camomilla/serializers/mixins/json.py,sha256=Iq5S7mUg5_Y4bsm6XN3ECJR07NGjCAQ21_wdxj6RgyY,1193
52
+ camomilla/serializers/mixins/language.py,sha256=VukEvPzTpKQfwB-z_RtoNIJ43N3OEgfjLpHvn9KuZDU,1205
53
+ camomilla/serializers/mixins/nesting.py,sha256=gCEU2UE_Y8e4VRnvT0AExFgwTfJm_jnSqa6l2SwZ3Mg,1432
54
+ camomilla/serializers/mixins/optimize.py,sha256=zAtbtk6kfGq9FnapqI8tVYOuMKd1IkHbAV6LffL61Z4,3845
55
+ camomilla/serializers/mixins/ordering.py,sha256=rXQOz47_U4IsMT6IBhySghcmJWMZgpPWHovDcZQG88k,1172
56
+ camomilla/serializers/mixins/page.py,sha256=Ida7dY9MQTv747_dpPGpo6u3iL5GX87z4zeVct-C36s,2132
57
+ camomilla/serializers/mixins/translation.py,sha256=Om2UT2EB4Xvp8SrIEvraY0kJXR9H54AsYBr9DKjsay8,4323
58
+ camomilla/storages/__init__.py,sha256=ytGgX59Ar8vFfYz7eV8z-j5yO_5FqxdZM25iyLnJuSA,131
59
+ camomilla/storages/default.py,sha256=GNzvV_JZpXMcfTkyXjw5CfK8EIBi3o-NXYBO0KAxD5M,351
60
+ camomilla/storages/optimize.py,sha256=VGSXZigzZC8LnPTqyTOpPA2Ba9EJB_KC5bcACoRs4GA,2762
61
+ camomilla/storages/overwrite.py,sha256=jvW3zHvXNzH9dIjeZmmfXo_O3K1ZQmLQzmlSKAOE8ZA,360
62
+ camomilla/templates/admin/camomilla/page/change_form.html,sha256=ig7rRUtylDZMINBQuVPpZLmeB4sOTV_VtqnTgzAyxEo,251
63
+ camomilla/templates/defaults/base.html,sha256=C2gCnQP1AkERPv5w00nVhZdfg2h_8DMoIkmdf2I-VVY,8166
64
+ camomilla/templates/defaults/articles/default.html,sha256=1f89jBvNtTa1mPAbC91yy8CzeAjTWO3hhQsTuQW5OKg,239
65
+ camomilla/templates/defaults/pages/default.html,sha256=bP81Qb6M56I-fBJMywWwEu_cnERtWIX28UkGrUSRU6M,144
66
+ camomilla/templates/defaults/parts/langswitch.html,sha256=AkaQzb2KNjRYCMLUn_jE31V36rwBIwp4MneirWPiBcI,3424
67
+ camomilla/templates/defaults/parts/menu.html,sha256=ReE-FfmfCNuNkJI33QqIfmMgLSBl3FTkWAhEa59aD3A,381
68
+ camomilla/templates/defaults/widgets/media_select_multiple.html,sha256=k2XYou8KkPuFLnPMkPJAFJ-zGJj2Xvu6R3ZmiKa3g7Q,3727
69
+ camomilla/templates_context/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
70
+ camomilla/templates_context/autodiscover.py,sha256=td7SCsqg3iNPnv1HDEDEpwWgWLjy5Zmc8Nbze1_J46I,1907
71
+ camomilla/templates_context/rendering.py,sha256=GfTR45_gC7WT7zTKPVXkBDwe22uF63A-DfZUW31woAU,3194
72
+ camomilla/templatetags/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
73
+ camomilla/templatetags/camomilla_filters.py,sha256=35x0-cWrRHeLhqypSLlJzEFY_fQDcRHiwZQpFgIsspE,692
74
+ camomilla/templatetags/menus.py,sha256=7fc4f9DDqtqG6wNb5_Q0km-fq0mqvGnbpR21qO1TJUw,960
75
+ camomilla/templatetags/model_extras.py,sha256=6WfVDYP_OfuVJd3cNGNA55Wj9uWdrbfOZQ0ua9Xt_vc,2257
76
+ camomilla/theme/__init__.py,sha256=eSyQRXyZR8d0tJQPRLwDd_1tXyRgb7TUvtlI-hfN620,22
77
+ camomilla/theme/apps.py,sha256=Ue2H80fbFgxkQyHeU2H0fWs9Y6d-EnHYv4zz824FSRk,1066
78
+ camomilla/theme/admin/__init__.py,sha256=TALAZaE-gWshSeGc6yy7VahdX5UfeCeoOE9Q5kJCEpM,2270
79
+ camomilla/theme/admin/pages.py,sha256=y3rL1nwZlytyD-YR_qqLiBAmjCAjkBY3v56V6JdhBvY,1908
80
+ camomilla/theme/admin/translations.py,sha256=iAjGM1A1aYrsz1FpeybROk6rn3Ddl_oUCwgU5oD8nSw,308
81
+ camomilla/theme/static/admin/css/responsive.css,sha256=yGq6qXrr8xEVsXTnprIBgkX-sMGZrNf0Kkh-xDxf6yE,157
82
+ camomilla/theme/static/admin/img/favicon.ico,sha256=qpKv_2MaGILvyihnD1Vq9Yk-ZXGkxWTW26ciMeBFMYU,15406
83
+ camomilla/theme/static/admin/img/logo.svg,sha256=WBAORIV_LzEOdcpq7iU6d0Nu3omgk2gn05f6LnPjfWg,3238
84
+ camomilla/theme/templates/admin/base.html,sha256=veKZ6KlnUYILeY4I2MYI18BbZMDec9MgzVzUqCHnjDc,254
85
+ camomilla/theme/templates/rosetta/base.html,sha256=s9Ijf1nZx8um30R5Gk3g-w-RwFGv2QGViHufyLLiiDY,16731
86
+ camomilla/utils/__init__.py,sha256=Ui7nzSh45UMMFtCGF1xFHKyJMNWflG_Nx72HAJHJHFM,100
87
+ camomilla/utils/getters.py,sha256=6j18grFAZ8BC70SriycFDTQFxTnudGn0uKGA83_Rclk,798
88
+ camomilla/utils/normalization.py,sha256=RDCZtjwpEEwjvfUjQl2bEWFKw7NxTzkXco72VeO2M9w,255
89
+ camomilla/utils/query_parser.py,sha256=TUScPzPVVJzaKdqy5NqtMOft3H5Bx6liXTVPM1yjH24,6303
90
+ camomilla/utils/seo.py,sha256=8p_a_TGgohenpJb094tT4mMxbn2xzW0qDILuTnjNocM,3324
91
+ camomilla/utils/setters.py,sha256=LV57SM65rL1_ZQkVzk9al_Q13lndVywXLkqgfIvgS0Y,915
92
+ camomilla/utils/templates.py,sha256=vu1z7Lcfr30rvKmztM4-mpl8bNpLkIV2U6vKQKzcyE0,910
93
+ camomilla/utils/translation.py,sha256=w5tvTInDLegWBb1TnDWo09ckKY3K6hajuNNsngZIxPQ,4205
94
+ camomilla/views/__init__.py,sha256=94QuOnnbfMMb17mruO2ydUt286-8zBmDxEPWrJv5Wog,178
95
+ camomilla/views/articles.py,sha256=qGxebOA5iTbGGe9PfbH40YBoDPKktH8FJongg6rh2R8,571
96
+ camomilla/views/contents.py,sha256=JxvnmgeK8JEmCMLzVG8pVq2DwvmjXtgnIdsDnn74tA4,1205
97
+ camomilla/views/decorators.py,sha256=hR--nTGQn2mMKDrWn-0Ildzbsvp11OfoWAtedKEzmiA,982
98
+ camomilla/views/languages.py,sha256=Rt_X7s3dbDBv4dxsQ9fnav_u0TAzzo8fGKBBx3esDsg,441
99
+ camomilla/views/medias.py,sha256=XYa-NTLLQmSSynpfrFT3av-K_r59aRns3dTGfYMj-0Q,3002
100
+ camomilla/views/menus.py,sha256=Kpygnf3tMKJ30gcblUES2NW83A37Vy75ecSGSvExGKM,3301
101
+ camomilla/views/pages.py,sha256=UL74_u-18QdAkjVl74AVWZbRarEdIPrANTzdcM4iqmE,1338
102
+ camomilla/views/tags.py,sha256=XcYRlcBFSPPY32lt7POb6fWPJL_8HsTo5JcHcAOiOKw,479
103
+ camomilla/views/users.py,sha256=_fvsKOEtep4SJLvMva2_q-HdLQT_1KlFNt4wcl3xCJk,3130
104
+ camomilla/views/base/__init__.py,sha256=t-7tqY_ep4Xi8YgB1sXDgNWQ5oh2YEUlfQWU5pltwJ0,1063
105
+ camomilla/views/mixins/__init__.py,sha256=Znv3fLYVy6lgu03Q_D8fTen4zMxI6VSRaLPDU8Cp7Ws,473
106
+ camomilla/views/mixins/bulk_actions.py,sha256=i0duWW6wey9m7I_V8-gPcHsbJyPEfSdMdj4h2i-CbPw,787
107
+ camomilla/views/mixins/language.py,sha256=hfnYznlVMrMLBdJ_f8dChJWENg7Kpt9m1yqavrdLm7E,1299
108
+ camomilla/views/mixins/optimize.py,sha256=iRPNkoeIIlJugk7DjJhDPaqeX7Opi7TxnUoMDnxJxUk,686
109
+ camomilla/views/mixins/ordering.py,sha256=mh7fqPyVCVJh84Nl2pYFQouzGxa-ANF3Wqv0pCb7OVU,4779
110
+ camomilla/views/mixins/pagination.py,sha256=Ssa5mMgAgyl7sUk0yum2uVifg6esdGmUTqMSJYacE40,5772
111
+ camomilla/views/mixins/permissions.py,sha256=TPmR3Hoa3BjeJu9rCE_7lpLOAupue4WI42C21HTo6X4,200
112
+ django_camomilla_cms-6.0.0.dist-info/licenses/LICENSE,sha256=kVS7zDrNkav2hLLXbOJwVdonY2ToApTK3khyJagGQoQ,1063
113
+ tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
114
+ tests/test_api.py,sha256=t03EFDezGgm4UJl8RIVvnTUkAGTB6ptm0G2lHBQ7ljc,1833
115
+ tests/test_camomilla_filters.py,sha256=rUK8iEyUNH28uTd8Ac13OikiH4Xi-V4wbtS-XjJoG24,1580
116
+ tests/test_media.py,sha256=n5PQmpMvw-a2epmq_60R0X-vVOa4BeyKMZkguGJzKa0,5243
117
+ tests/test_menu.py,sha256=hrTikgXNnry1bS-t5K7UGYreEJ3m-FU0r4pduumwTd4,3791
118
+ tests/test_model_api.py,sha256=ml3OlLuBfcnr2EMjwQLvVDPT2adSQ7WS4IxxXKD1InU,4121
119
+ tests/test_model_api_permissions.py,sha256=lUlcYAOasFFQjMFnqhGXlXriCH-f6xdYSCn1Gqf1eSU,1838
120
+ tests/test_model_api_register.py,sha256=txKaVTGt-DGrmI-6xcUEluPd7ArNi80VvlqBVXdH8zk,13555
121
+ tests/test_models.py,sha256=WJs8lxWZWn1l7X3a_QFVc8fF5LHTsI8bc3uhQe6-o-Q,684
122
+ tests/test_pages.py,sha256=aXKI0l12lc6jmY3uJXDNwznVNH7SEIiujANvSo_rhIo,11911
123
+ tests/test_query_parser.py,sha256=R9l0L2QDEDcm2b6IFUhyf7wMXLzL9RySLkzKTWRtBkE,2097
124
+ tests/test_templates_context.py,sha256=zGdmbQMGNXB2V_15BaQDIgqFMnVjBAw969n1tu3m7HY,5626
125
+ tests/test_utils.py,sha256=o_FG7XOxLePOBfwBr4sk09gej0onWNw9t2-gSjGmgNg,3741
126
+ tests/fixtures/__init__.py,sha256=ixyA6ZsmYbiKEsjQGOGoG4KyJmwWrf-qeoQjQG3J66U,426
127
+ tests/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
128
+ tests/utils/api.py,sha256=TYcDXeILHtBwzwG0acwPFmiqMZnlF9VnLB0Ydhg55vA,865
129
+ tests/utils/media.py,sha256=-cnrQzzVuhNSb5rT5xMUs5f3yYpBnS0fVGDcjgsb8lw,291
130
+ django_camomilla_cms-6.0.0.dist-info/METADATA,sha256=z4kbFog0-jwgDE5gTH-qml5b-ivUVnFdVmvswByJkcs,4674
131
+ django_camomilla_cms-6.0.0.dist-info/WHEEL,sha256=JNWh1Fm1UdwIQV075glCn4MVuCRs0sotJIq-J6rbxCU,109
132
+ django_camomilla_cms-6.0.0.dist-info/top_level.txt,sha256=G9VIGBmMMqC7JEckoTgXKmC6T2BR75QRkqRnngw1_lo,16
133
+ django_camomilla_cms-6.0.0.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: bdist_wheel (0.38.4)
2
+ Generator: setuptools (80.9.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py2-none-any
5
5
  Tag: py3-none-any
@@ -0,0 +1,14 @@
1
+ import json
2
+ import os
3
+ from django.core.files.uploadedfile import SimpleUploadedFile
4
+
5
+
6
+ def load_json_fixture(filename):
7
+ with open(os.path.join(os.path.dirname(__file__), "json", filename), "r") as f:
8
+ return json.load(f)
9
+
10
+
11
+ def load_asset(filename):
12
+ with open(os.path.join(os.path.dirname(__file__), "assets", filename), "rb") as f:
13
+ up_file = SimpleUploadedFile(filename, f.read())
14
+ return up_file
tests/test_api.py CHANGED
@@ -1,74 +1,57 @@
1
1
  import pytest
2
- from django.contrib.auth.models import User
3
2
  from rest_framework.test import APIClient
4
-
5
- from camomilla.models import Tag, Category
3
+ from .utils.api import login_superuser
4
+ from camomilla.models import Tag
6
5
 
7
6
  client = APIClient()
8
7
 
9
8
 
10
- def login_superuser():
11
- User.objects.create_superuser("admin", "myemail@test.com", "adminadmin")
12
- response = client.post(
13
- "/api/camomilla/token-auth/", {"username": "admin", "password": "adminadmin"}
14
- )
15
- return response.json()["token"]
16
-
17
-
18
9
  @pytest.mark.django_db
19
10
  def test_create_tag_no_access():
20
- response = client.post("/api/camomilla/tags/", {"title": "First tag"})
21
- assert response.json()["detail"] == "Authentication credentials were not provided."
22
- assert response.status_code == 403
11
+ response = client.post("/api/camomilla/tags/", {"name_en": "First tag"})
12
+ assert response.status_code == 401
23
13
 
24
14
 
25
15
  @pytest.mark.django_db
26
16
  def test_crud_tag():
27
- ## Create
17
+ # Create
28
18
  token = login_superuser()
29
19
  client.credentials(HTTP_AUTHORIZATION="Token " + token)
30
- response = client.post("/api/camomilla/tags/", {"title": "Primo tag"})
31
- assert response.json()["title"] == "Primo tag"
32
- assert response.json()["language_code"] == "it"
20
+ response = client.post("/api/camomilla/tags/", {"name_en": "First tag"})
33
21
 
22
+ assert response.json()["name"] == "First tag"
34
23
  assert len(Tag.objects.all()) == 1
35
24
  assert response.status_code == 201
36
25
 
37
- ## Create another with a different language
38
- response = client.post(
39
- "/api/camomilla/tags/", {"title": "Second tag", "language_code": "en"}
40
- )
41
- assert response.json()["title"] == "Second tag"
42
- assert response.json()["language_code"] == "en"
43
-
26
+ # Create another with a different language
27
+ response = client.post("/api/camomilla/tags/", {"name_it": "Secondo tag"})
28
+ assert response.json()["translations"]["it"]["name"] == "Secondo tag"
44
29
  assert len(Tag.objects.all()) == 2
45
-
46
30
  assert response.status_code == 201
47
31
 
48
- ## Translate the second one in italian
32
+ # Translate the second one in english
49
33
  response = client.patch(
50
- "/api/camomilla/tags/2/", {"title": "Secondo tag", "language_code": "it"}
34
+ "/api/camomilla/tags/2/",
35
+ {"translations": {"en": {"name": "Second tag"}}},
36
+ format="json",
51
37
  )
52
- assert response.json()["title"] == "Secondo tag"
53
- assert response.json()["language_code"] == "it"
54
-
38
+ assert response.json()["translations"]["en"]["name"] == "Second tag"
39
+ assert response.json()["translations"]["it"]["name"] == "Secondo tag"
55
40
  assert len(Tag.objects.all()) == 2
56
41
 
57
42
  assert response.status_code == 200
58
43
 
59
- ## Get the tags in 🇮🇹
44
+ # Get the tags in english
60
45
  response = client.get("/api/camomilla/tags/")
61
46
 
62
- assert response.json()[0]["title"] == "Secondo tag"
63
- assert response.json()[0]["language_code"] == "it"
47
+ assert response.json()[0]["name"] == "Second tag"
64
48
 
65
- ## Get the tags in 🇬🇧 with fallbacks!
66
- response = client.get("/api/camomilla/tags/?language=en")
49
+ # Get the tags in italianith fallbacks!
50
+ response = client.get("/api/camomilla/tags/?language=it")
67
51
 
68
- assert response.json()[0]["title"] == "Second tag"
69
- assert response.json()[0]["language_code"] == "en"
52
+ assert response.json()[0]["name"] == "Secondo tag"
70
53
 
71
- ## Delete the tag
54
+ # Delete the tag
72
55
  response = client.delete("/api/camomilla/tags/2/")
73
56
 
74
57
  assert len(Tag.objects.all()) == 1
@@ -17,31 +17,29 @@ class CamomillaFiltersTestCase(TestCase):
17
17
  pass
18
18
 
19
19
  def test_filter_content(self):
20
+ Page.objects.create(
21
+ identifier="path", title="Path", permalink="/path", status="PUB"
22
+ )
20
23
  request_factory = RequestFactory()
21
24
  request = request_factory.get("/path")
22
25
  request.META["HTTP_HOST"] = "localhost"
23
- page = Page.get(request, identifier="home")
26
+ page = Page.get(request)
24
27
  content = filter_content(page, "content1")
25
28
  self.assertEqual(content.identifier, "content1")
26
29
  self.assertEqual(content.content, "")
27
30
  content.content = "Hello World!"
28
31
  content.save()
29
- page = Page.get(request, identifier="home")
32
+ page = Page.get(request)
30
33
  content = filter_content(page, "content1")
31
34
  self.assertEqual(content.identifier, "content1")
32
35
  self.assertEqual(content.content, "Hello World!")
33
36
 
34
37
  def test_filter_alternate_urls(self):
35
- request = RequestFactory().get("/path", HTTP_HOST="localhost:8000")
38
+ Page.objects.create(
39
+ identifier="path", title="Path", permalink="/path", status="PUB"
40
+ )
41
+ request = RequestFactory().get("/path")
36
42
  request.META["HTTP_HOST"] = "localhost"
37
- page = Page.get(request, identifier="home")
43
+ page = Page.get(request)
38
44
  alt_urls = dict(alternate_urls(page, request))
39
- self.assertEqual(alt_urls, {})
40
-
41
- request = RequestFactory().get("/about", HTTP_HOST="localhost:8000")
42
- request.META["HTTP_HOST"] = "localhost"
43
- page = Page.get(request, identifier="about")
44
- alt_urls = dict(alternate_urls(page, request))
45
- self.assertEqual(alt_urls["it"], "http://localhost/about")
46
- self.assertEqual(alt_urls["en"], "http://localhost/en/about")
47
- self.assertEqual(alt_urls["de"], "http://localhost/de/about")
45
+ self.assertEqual(alt_urls, {"it": None, "en": "/path/"})