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
tests/test_utils.py
CHANGED
@@ -13,74 +13,74 @@ from django.utils.translation import activate, get_language
|
|
13
13
|
from requests import RequestException
|
14
14
|
|
15
15
|
|
16
|
-
class UtilsTestCase(TestCase):
|
17
|
-
|
18
|
-
|
16
|
+
# class UtilsTestCase(TestCase):
|
17
|
+
# def setUp(self):
|
18
|
+
# pass
|
19
19
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
20
|
+
# def test_get_host_url(self):
|
21
|
+
# """Our beloved get_host_url utility"""
|
22
|
+
# request_factory = RequestFactory()
|
23
|
+
# request = request_factory.get("/path")
|
24
|
+
# request.META["HTTP_HOST"] = "localhost"
|
25
|
+
# host_url = get_host_url(request)
|
26
|
+
# self.assertEqual(host_url, "http://localhost")
|
27
|
+
# host_url = get_host_url(None)
|
28
|
+
# self.assertEqual(host_url, None)
|
29
29
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
30
|
+
# def test_get_complete_url(self):
|
31
|
+
# """Our beloved get_complete_url utility"""
|
32
|
+
# request_factory = RequestFactory()
|
33
|
+
# request = request_factory.get("/path")
|
34
|
+
# request.META["HTTP_HOST"] = "localhost"
|
35
|
+
# complete_url = get_complete_url(request, "path")
|
36
|
+
# self.assertEqual(complete_url, "http://localhost/path")
|
37
|
+
# complete_url = get_complete_url(request, "path", "it")
|
38
|
+
# self.assertEqual(complete_url, "http://localhost/path")
|
39
|
+
# complete_url = get_complete_url(request, "path", "fr")
|
40
|
+
# self.assertEqual(complete_url, "http://localhost/fr/path")
|
41
41
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
42
|
+
# def test_get_page_with_default_seo(self):
|
43
|
+
# """Our beloved get_seo utility with auto attributes"""
|
44
|
+
# request_factory = RequestFactory()
|
45
|
+
# request = request_factory.get("/path")
|
46
|
+
# request.META["HTTP_HOST"] = "localhost"
|
47
|
+
# page = Page.get(request, identifier="home")
|
48
|
+
# self.assertEqual(page.og_url, "http://localhost/path")
|
49
|
+
# self.assertEqual(page.canonical, "http://localhost/path")
|
50
50
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
51
|
+
# def test_get_article_with_default_seo(self):
|
52
|
+
# """Our beloved get_seo utility with auto attributes"""
|
53
|
+
# request_factory = RequestFactory()
|
54
|
+
# request = request_factory.get("/path")
|
55
|
+
# request.META["HTTP_HOST"] = "localhost"
|
56
|
+
# Article.objects.create(permalink="main")
|
57
|
+
# article = Article.get(request, permalink="main")
|
58
|
+
# self.assertEqual(article.og_url, "http://localhost/path")
|
59
|
+
# self.assertEqual(article.canonical, "http://localhost/path")
|
60
60
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
61
|
+
# def test_compile_seo_overwrite(self):
|
62
|
+
# """Our beloved get_seo utility with auto attributes"""
|
63
|
+
# request_factory = RequestFactory()
|
64
|
+
# request = request_factory.get("/path")
|
65
|
+
# request.META["HTTP_HOST"] = "localhost"
|
66
|
+
# article = Article.objects.create(permalink="main")
|
67
|
+
# article.canonical = "/myarticle"
|
68
|
+
# article.og_url = "/myarticle"
|
69
|
+
# article.save()
|
70
|
+
# article = Article.get(request, permalink="main")
|
71
|
+
# self.assertEqual(article.og_url, "http://localhost/myarticle")
|
72
|
+
# self.assertEqual(article.canonical, "http://localhost/myarticle")
|
73
73
|
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
74
|
+
# def test_get_article_with_redirect(self):
|
75
|
+
# """Our beloved get_seo utility with auto attributes"""
|
76
|
+
# request_factory = RequestFactory()
|
77
|
+
# request = request_factory.get("/articles/articolo-1")
|
78
|
+
# request.META["HTTP_HOST"] = "localhost"
|
79
79
|
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
80
|
+
# article = Article.objects.create(permalink="article-1", language_code="en")
|
81
|
+
# article.translate("it")
|
82
|
+
# article.permalink = "articolo-1"
|
83
|
+
# article.save()
|
84
|
+
# self.assertRaises(NeedARedirect, Article.get, request, permalink="article-1")
|
85
|
+
# activate("de")
|
86
|
+
# self.assertRaises(Http404, Article.get, request, permalink="article-1")
|
tests/utils/__init__.py
ADDED
File without changes
|
tests/utils/api.py
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
from django.contrib.auth.models import User
|
2
|
+
from rest_framework.test import APIClient
|
3
|
+
|
4
|
+
client = APIClient()
|
5
|
+
|
6
|
+
|
7
|
+
def login_superuser():
|
8
|
+
User.objects.create_superuser("admin", "admin@test.com", "adminadmin")
|
9
|
+
response = client.post(
|
10
|
+
"/api/camomilla/token-auth/", {"username": "admin", "password": "adminadmin"}
|
11
|
+
)
|
12
|
+
return response.json()["token"]
|
13
|
+
|
14
|
+
|
15
|
+
def login_user():
|
16
|
+
User.objects.create_user("user", "user@test.com", "useruser")
|
17
|
+
response = client.post(
|
18
|
+
"/api/camomilla/token-auth/", {"username": "user", "password": "useruser"}
|
19
|
+
)
|
20
|
+
return response.json()["token"]
|
21
|
+
|
22
|
+
|
23
|
+
def login_staff():
|
24
|
+
User.objects.create_user("staff", "staff@test.com", "staffstaff", is_staff=True)
|
25
|
+
response = client.post(
|
26
|
+
"/api/camomilla/token-auth/", {"username": "staff", "password": "staffstaff"}
|
27
|
+
)
|
28
|
+
return response.json()["token"]
|
tests/utils/media.py
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
import os
|
2
|
+
from tests.fixtures import load_asset
|
3
|
+
from django.conf import settings
|
4
|
+
|
5
|
+
|
6
|
+
def load_asset_and_remove_media(filename):
|
7
|
+
asset = load_asset(filename)
|
8
|
+
if os.path.exists(f"{settings.MEDIA_ROOT}/{filename}"):
|
9
|
+
os.remove(f"{settings.MEDIA_ROOT}/{filename}")
|
10
|
+
return asset
|
camomilla/admin.py
DELETED
@@ -1,98 +0,0 @@
|
|
1
|
-
from django.contrib import admin
|
2
|
-
|
3
|
-
from django import forms
|
4
|
-
from django.http import HttpResponse
|
5
|
-
|
6
|
-
from .models import Article, Tag, Category, Content, Media, Page, MediaFolder
|
7
|
-
from ckeditor_uploader.widgets import CKEditorUploadingWidget
|
8
|
-
|
9
|
-
|
10
|
-
from hvad.admin import TranslatableAdmin
|
11
|
-
from hvad.forms import TranslatableModelForm
|
12
|
-
|
13
|
-
from django.conf import settings
|
14
|
-
from django.utils.translation import gettext_lazy as _
|
15
|
-
|
16
|
-
|
17
|
-
class UserProfileAdmin(admin.ModelAdmin):
|
18
|
-
pass
|
19
|
-
|
20
|
-
|
21
|
-
class ArticleAdminForm(TranslatableModelForm):
|
22
|
-
content = forms.CharField(widget=CKEditorUploadingWidget())
|
23
|
-
|
24
|
-
class Meta:
|
25
|
-
model = Article
|
26
|
-
exclude = ("slug",)
|
27
|
-
|
28
|
-
|
29
|
-
class ArticleAdmin(TranslatableAdmin):
|
30
|
-
filter_horizontal = ("tags", "categories")
|
31
|
-
form = ArticleAdminForm
|
32
|
-
|
33
|
-
|
34
|
-
class TagAdmin(TranslatableAdmin):
|
35
|
-
pass
|
36
|
-
|
37
|
-
|
38
|
-
class CategoryAdmin(TranslatableAdmin):
|
39
|
-
pass
|
40
|
-
|
41
|
-
|
42
|
-
class MediaFolderAdmin(TranslatableAdmin):
|
43
|
-
pass
|
44
|
-
|
45
|
-
|
46
|
-
class ContentAdminForm(TranslatableModelForm):
|
47
|
-
exclude = ("permalink",)
|
48
|
-
content = forms.CharField(widget=CKEditorUploadingWidget())
|
49
|
-
|
50
|
-
class Meta:
|
51
|
-
model = Content
|
52
|
-
|
53
|
-
|
54
|
-
class ContentAdmin(TranslatableAdmin):
|
55
|
-
form = ContentAdminForm
|
56
|
-
|
57
|
-
|
58
|
-
class MediaAdmin(TranslatableAdmin):
|
59
|
-
exclude = (
|
60
|
-
"thumbnail",
|
61
|
-
"size",
|
62
|
-
"image_props",
|
63
|
-
)
|
64
|
-
readonly_fields = ("image_preview", "image_thumb_preview")
|
65
|
-
list_display = (
|
66
|
-
"__str__",
|
67
|
-
"name",
|
68
|
-
"image_thumb_preview",
|
69
|
-
)
|
70
|
-
|
71
|
-
def response_add(self, request, obj):
|
72
|
-
if request.GET.get("_popup", ""):
|
73
|
-
return HttpResponse(
|
74
|
-
"""
|
75
|
-
<script type="text/javascript">
|
76
|
-
opener.dismissAddRelatedObjectPopup(window, %s, '%s');
|
77
|
-
</script>"""
|
78
|
-
% (obj.id, obj.json_repr)
|
79
|
-
)
|
80
|
-
else:
|
81
|
-
return super(MediaAdmin, self).response_add(request, obj)
|
82
|
-
|
83
|
-
|
84
|
-
class PageAdmin(TranslatableAdmin):
|
85
|
-
exclude = ("permalink",)
|
86
|
-
|
87
|
-
|
88
|
-
admin.site.register(Article, ArticleAdmin)
|
89
|
-
admin.site.register(Category, CategoryAdmin)
|
90
|
-
admin.site.register(MediaFolder, MediaFolderAdmin)
|
91
|
-
admin.site.register(Tag, TagAdmin)
|
92
|
-
admin.site.register(Content, ContentAdmin)
|
93
|
-
admin.site.register(Media, MediaAdmin)
|
94
|
-
admin.site.register(Page, PageAdmin)
|
95
|
-
|
96
|
-
admin.site.index_title = "{0} {1}".format(
|
97
|
-
_("Administration panel for"), getattr(settings, "PROJECT_TITLE", "Camomilla")
|
98
|
-
)
|