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.
- camomilla/__init__.py +8 -2
- camomilla/apps.py +9 -1
- camomilla/context_processors.py +6 -0
- camomilla/contrib/modeltranslation/__init__.py +0 -0
- camomilla/contrib/modeltranslation/hvad_migration.py +126 -0
- camomilla/dynamic_pages_urls.py +33 -0
- camomilla/fields/__init__.py +13 -0
- camomilla/{fields.py → fields/json.py} +15 -18
- camomilla/management/commands/regenerate_thumbnails.py +0 -1
- camomilla/managers/__init__.py +3 -0
- camomilla/managers/pages.py +116 -0
- camomilla/model_api.py +86 -0
- camomilla/models/__init__.py +5 -6
- camomilla/models/article.py +26 -44
- camomilla/models/content.py +8 -15
- camomilla/models/media.py +70 -97
- camomilla/models/menu.py +106 -0
- camomilla/models/mixins/__init__.py +10 -48
- camomilla/models/page.py +521 -20
- camomilla/openapi/__init__.py +0 -0
- camomilla/openapi/schema.py +67 -0
- camomilla/parsers.py +0 -1
- camomilla/redirects.py +10 -0
- camomilla/serializers/__init__.py +2 -0
- camomilla/serializers/article.py +5 -10
- camomilla/serializers/base/__init__.py +21 -17
- camomilla/serializers/content_type.py +17 -0
- camomilla/serializers/fields/__init__.py +6 -20
- camomilla/serializers/fields/file.py +5 -0
- camomilla/serializers/fields/related.py +24 -4
- camomilla/serializers/media.py +6 -8
- camomilla/serializers/menu.py +17 -0
- camomilla/serializers/mixins/__init__.py +23 -187
- camomilla/serializers/mixins/fields.py +20 -0
- camomilla/serializers/mixins/filter_fields.py +57 -0
- camomilla/serializers/mixins/json.py +34 -0
- camomilla/serializers/mixins/language.py +32 -0
- camomilla/serializers/mixins/nesting.py +35 -0
- camomilla/serializers/mixins/optimize.py +91 -0
- camomilla/serializers/mixins/ordering.py +34 -0
- camomilla/serializers/mixins/page.py +58 -0
- camomilla/serializers/mixins/translation.py +103 -0
- camomilla/serializers/page.py +53 -4
- camomilla/serializers/user.py +5 -4
- camomilla/serializers/utils.py +38 -0
- camomilla/serializers/validators.py +51 -0
- camomilla/settings.py +118 -0
- camomilla/sitemap.py +30 -0
- camomilla/storages/__init__.py +4 -0
- camomilla/storages/default.py +12 -0
- camomilla/storages/optimize.py +71 -0
- camomilla/{storages.py → storages/overwrite.py} +2 -2
- camomilla/templates/admin/camomilla/page/change_form.html +10 -0
- camomilla/templates/defaults/articles/default.html +7 -0
- camomilla/templates/defaults/base.html +170 -0
- camomilla/templates/defaults/pages/default.html +3 -0
- camomilla/templates/defaults/parts/langswitch.html +83 -0
- camomilla/templates/defaults/parts/menu.html +15 -0
- camomilla/templates_context/__init__.py +0 -0
- camomilla/templates_context/autodiscover.py +51 -0
- camomilla/templates_context/rendering.py +89 -0
- camomilla/templatetags/camomilla_filters.py +6 -5
- camomilla/templatetags/menus.py +37 -0
- camomilla/templatetags/model_extras.py +77 -0
- camomilla/theme/__init__.py +1 -1
- camomilla/theme/admin/__init__.py +99 -0
- camomilla/theme/admin/pages.py +46 -0
- camomilla/theme/admin/translations.py +13 -0
- camomilla/theme/apps.py +38 -0
- camomilla/theme/static/admin/css/responsive.css +5 -1021
- camomilla/theme/static/admin/img/favicon.ico +0 -0
- camomilla/theme/static/admin/img/logo.svg +31 -0
- camomilla/theme/templates/admin/base.html +7 -0
- camomilla/theme/templates/rosetta/base.html +196 -0
- camomilla/translation.py +61 -0
- camomilla/urls.py +38 -17
- camomilla/utils/__init__.py +4 -0
- camomilla/utils/getters.py +27 -0
- camomilla/utils/normalization.py +7 -0
- camomilla/utils/query_parser.py +167 -0
- camomilla/{utils.py → utils/seo.py} +13 -15
- camomilla/utils/setters.py +37 -0
- camomilla/utils/templates.py +32 -0
- camomilla/utils/translation.py +114 -0
- camomilla/views/__init__.py +1 -1
- camomilla/views/articles.py +5 -7
- camomilla/views/base/__init__.py +35 -5
- camomilla/views/contents.py +6 -11
- camomilla/views/decorators.py +26 -0
- camomilla/views/medias.py +24 -19
- camomilla/views/menus.py +81 -0
- camomilla/views/mixins/__init__.py +17 -73
- camomilla/views/mixins/bulk_actions.py +22 -0
- camomilla/views/mixins/language.py +33 -0
- camomilla/views/mixins/optimize.py +18 -0
- camomilla/views/mixins/ordering.py +2 -2
- camomilla/views/mixins/pagination.py +12 -18
- camomilla/views/mixins/permissions.py +6 -0
- camomilla/views/pages.py +28 -6
- camomilla/views/tags.py +5 -6
- camomilla/views/users.py +7 -12
- django_camomilla_cms-6.0.0.dist-info/METADATA +123 -0
- django_camomilla_cms-6.0.0.dist-info/RECORD +133 -0
- {django_camomilla_cms-5.8.5.dist-info → django_camomilla_cms-6.0.0.dist-info}/WHEEL +1 -1
- tests/fixtures/__init__.py +14 -0
- tests/test_api.py +22 -39
- tests/test_camomilla_filters.py +11 -13
- tests/test_media.py +152 -0
- tests/test_menu.py +112 -0
- tests/test_model_api.py +113 -0
- tests/test_model_api_permissions.py +44 -0
- tests/test_model_api_register.py +355 -0
- tests/test_pages.py +351 -0
- tests/test_query_parser.py +58 -0
- tests/test_templates_context.py +149 -0
- tests/test_utils.py +64 -64
- tests/utils/__init__.py +0 -0
- tests/utils/api.py +28 -0
- tests/utils/media.py +10 -0
- camomilla/admin.py +0 -98
- camomilla/migrations/0001_initial.py +0 -577
- camomilla/migrations/0002_auto_20200214_1127.py +0 -33
- camomilla/migrations/0003_auto_20210130_1610.py +0 -30
- camomilla/migrations/0004_auto_20210511_0937.py +0 -25
- camomilla/migrations/0005_media_image_props.py +0 -19
- camomilla/migrations/0006_auto_20220103_1845.py +0 -35
- camomilla/migrations/0007_auto_20220211_1622.py +0 -18
- camomilla/migrations/0008_auto_20220309_1616.py +0 -60
- camomilla/migrations/0009_article__hvad_query_category__hvad_query_and_more.py +0 -165
- camomilla/migrations/0010_auto_20220802_1406.py +0 -83
- camomilla/migrations/0011_auto_20220902_1000.py +0 -15
- camomilla/models/category.py +0 -25
- camomilla/models/tag.py +0 -19
- camomilla/theme/static/admin/img/logo.png +0 -0
- camomilla/theme/templates/admin/base_site.html +0 -18
- camomilla/views/categories.py +0 -13
- django_camomilla_cms-5.8.5.dist-info/METADATA +0 -62
- django_camomilla_cms-5.8.5.dist-info/RECORD +0 -76
- tests/urls.py +0 -21
- /camomilla/{migrations → contrib}/__init__.py +0 -0
- /camomilla/templates/{camomilla → defaults}/widgets/media_select_multiple.html +0 -0
- {django_camomilla_cms-5.8.5.dist-info → django_camomilla_cms-6.0.0.dist-info/licenses}/LICENSE +0 -0
- {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
|
-
|
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
|
-
|
99
|
-
|
100
|
-
|
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
|
|
camomilla/views/pages.py
CHANGED
@@ -1,13 +1,35 @@
|
|
1
|
-
from .
|
2
|
-
from .
|
3
|
-
from
|
4
|
-
from
|
5
|
-
from
|
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 .
|
2
|
-
from .
|
3
|
-
from
|
4
|
-
from
|
5
|
-
from
|
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 .
|
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
|
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
|
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
|
+
[](https://pypi.org/project/django-camomilla-cms)  [](./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
|
+
- 🧘♀️ Built on top of the django framework
|
51
|
+
- 🥨 Beaked page abstract model to let you manage everything you need as a page.
|
52
|
+
- 🏞️ Optimized media management with autoresize
|
53
|
+
- 👯 Enable relations inside django JSONFields
|
54
|
+
- ⚡️ AutoCreate api endpoints from models
|
55
|
+
- 🚧 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,,
|
@@ -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
|
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/", {"
|
21
|
-
assert response.
|
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
|
-
|
17
|
+
# Create
|
28
18
|
token = login_superuser()
|
29
19
|
client.credentials(HTTP_AUTHORIZATION="Token " + token)
|
30
|
-
response = client.post("/api/camomilla/tags/", {"
|
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
|
-
|
38
|
-
response = client.post(
|
39
|
-
|
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
|
-
|
32
|
+
# Translate the second one in english
|
49
33
|
response = client.patch(
|
50
|
-
"/api/camomilla/tags/2/",
|
34
|
+
"/api/camomilla/tags/2/",
|
35
|
+
{"translations": {"en": {"name": "Second tag"}}},
|
36
|
+
format="json",
|
51
37
|
)
|
52
|
-
assert response.json()["
|
53
|
-
assert response.json()["
|
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
|
-
|
44
|
+
# Get the tags in english
|
60
45
|
response = client.get("/api/camomilla/tags/")
|
61
46
|
|
62
|
-
assert response.json()[0]["
|
63
|
-
assert response.json()[0]["language_code"] == "it"
|
47
|
+
assert response.json()[0]["name"] == "Second tag"
|
64
48
|
|
65
|
-
|
66
|
-
response = client.get("/api/camomilla/tags/?language=
|
49
|
+
# Get the tags in italianith fallbacks!
|
50
|
+
response = client.get("/api/camomilla/tags/?language=it")
|
67
51
|
|
68
|
-
assert response.json()[0]["
|
69
|
-
assert response.json()[0]["language_code"] == "en"
|
52
|
+
assert response.json()[0]["name"] == "Secondo tag"
|
70
53
|
|
71
|
-
|
54
|
+
# Delete the tag
|
72
55
|
response = client.delete("/api/camomilla/tags/2/")
|
73
56
|
|
74
57
|
assert len(Tag.objects.all()) == 1
|
tests/test_camomilla_filters.py
CHANGED
@@ -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
|
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
|
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
|
-
|
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
|
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/"})
|