Skip to content

Commit 81aef82

Browse files
authored
Merge branch 'exp_cms4_navbar' into navbar
2 parents 76cd22e + 3873118 commit 81aef82

File tree

20 files changed

+230
-74
lines changed

20 files changed

+230
-74
lines changed

.travis.yml

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,18 @@
1+
dist: focal
12
language: python
23

34
python:
4-
- 3.5
5-
- 3.6
6-
- 3.7
75
- 3.8
86

97
env:
10-
- DJANGOVER=django21 CMSVER=cms36
11-
- DJANGOVER=django22 CMSVER=cms36
8+
129
- DJANGOVER=django22 CMSVER=cms37
1310
- DJANGOVER=django30 CMSVER=cms37
11+
- DJANGOVER=django22 CMSVER=cms40
12+
- DJANGOVER=django30 CMSVER=cms40
1413

1514
matrix:
1615
allow_failures:
17-
- python: 3.8
18-
env: DJANGOVER=django21 CMSVER=cms36
19-
- python: 3.8
20-
env: DJANGOVER=django22 CMSVER=cms36
2116
- python: 3.8
2217
env: DJANGOVER=django30 CMSVER=cms37
2318

cmsplugin_cascade/admin.py

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,12 @@
44
from django.contrib import admin
55
from django.contrib.sites.shortcuts import get_current_site
66
from django.forms import Media, widgets
7-
from django.db.models import Q
87
from django.http import JsonResponse, HttpResponseForbidden, HttpResponseNotFound
98
from django.urls import reverse
109
from django.utils.translation import get_language_from_request
1110

12-
from cms.models.pagemodel import Page
1311
from cms.extensions import PageExtensionAdmin
14-
from cms.utils.page import get_page_from_path
12+
from cmsplugin_cascade.utils_helpers import get_page_from_path, get_matching_published_pages
1513
from cmsplugin_cascade.models import CascadePage, IconFont
1614
from cmsplugin_cascade.link.forms import format_page_link
1715

@@ -79,12 +77,7 @@ def get_published_pagelist(self, request, *args, **kwargs):
7977
return JsonResponse(data)
8078

8179
# otherwise resolve by search term
82-
matching_published_pages = Page.objects.published().public().filter(
83-
Q(title_set__title__icontains=query_term, title_set__language=language)
84-
| Q(title_set__path__icontains=query_term, title_set__language=language)
85-
| Q(title_set__menu_title__icontains=query_term, title_set__language=language)
86-
| Q(title_set__page_title__icontains=query_term, title_set__language=language)
87-
).distinct().order_by('title_set__title').iterator()
80+
matching_published_pages = get_matching_published_pages(query_term,language)
8881

8982
for page in matching_published_pages:
9083
data['results'].append(self.get_result_set(language, page))

cmsplugin_cascade/bootstrap4/container.py

Lines changed: 25 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,10 @@
1010
from cmsplugin_cascade import app_settings
1111
from cmsplugin_cascade.bootstrap4.grid import Breakpoint
1212
from cmsplugin_cascade.forms import ManageChildrenFormMixin
13+
from cmsplugin_cascade.utils_helpers import CMS_, get_ancestor
1314
from .plugin_base import BootstrapPluginBase
1415
from . import grid
1516

16-
1717
def get_widget_choices():
1818
breakpoints = app_settings.CMSPLUGIN_CASCADE['bootstrap4']['fluid_bounds']
1919
widget_choices = []
@@ -104,6 +104,8 @@ def get_css_classes(cls, obj):
104104
def save_model(self, request, obj, form, change):
105105
super().save_model(request, obj, form, change)
106106
obj.sanitize_children()
107+
obj.sanitize_related_siblings()
108+
107109

108110
plugin_pool.register_plugin(BootstrapContainerPlugin)
109111

@@ -127,9 +129,8 @@ class Meta:
127129
class RowGridMixin(object):
128130
def get_grid_instance(self):
129131
row = grid.Bootstrap4Row()
130-
query = Q(plugin_type='BootstrapContainerPlugin') | Q(plugin_type='BootstrapColumnPlugin') \
131-
| Q(plugin_type='BootstrapJumbotronPlugin')
132-
container = self.get_ancestors().order_by('depth').filter(query).last().get_bound_plugin().get_grid_instance()
132+
class_ancestor_name = ['BootstrapContainerPlugin', 'BootstrapColumnPlugin', 'BootstrapJumbotronPlugin']
133+
container = get_ancestor( class_ancestor_name , plugin=self).get_bound_plugin().get_grid_instance()
133134
container.add_row(row)
134135
return row
135136

@@ -161,11 +162,11 @@ class ColumnGridMixin(object):
161162
'xs-column-offset', 'sm-column-offset', 'md-column-offset', 'lg-column-offset', 'xs-column-offset']
162163
def get_grid_instance(self):
163164
column = None
164-
query = Q(plugin_type='BootstrapRowPlugin')
165-
row_obj = self.get_ancestors().order_by('depth').filter(query).last().get_bound_plugin()
165+
row_obj = get_ancestor(['BootstrapRowPlugin'], plugin=self).get_bound_plugin()
166166
# column_siblings = row_obj.get_descendants().order_by('depth').filter(plugin_type='BootstrapColumnPlugin')
167167
row = row_obj.get_grid_instance()
168-
for column_sibling in self.get_siblings():
168+
siblings = self.parent.get_children()
169+
for column_sibling in siblings:
169170
classes = [val for key, val in column_sibling.get_bound_plugin().glossary.items()
170171
if key in self.valid_keys and val]
171172
if column_sibling.pk == self.pk:
@@ -195,17 +196,17 @@ def choose_help_text(*phrases):
195196
return phrases[1].format(bs4_breakpoints[first].min)
196197
else:
197198
return phrases[2]
198-
199-
if 'parent' in self._cms_initial_attributes:
200-
container=self._cms_initial_attributes['parent'].get_ancestors().order_by('depth').last().get_bound_plugin()
201-
else:
202-
containers=obj.get_ancestors().filter(plugin_type='BootstrapContainerPlugin')
203-
if containers:
204-
container=containers.order_by('depth').last().get_bound_plugin()
205-
else:
206-
jumbotrons=obj.get_ancestors().filter(plugin_type='BootstrapJumbotronPlugin')
207-
container=jumbotrons.order_by('depth').last().get_bound_plugin()
208-
breakpoints = container.glossary['breakpoints']
199+
200+
container = get_ancestor(['BootstrapContainerPlugin','BootstrapJumbotronPlugin'],
201+
_cms_initial_attributes=self._cms_initial_attributes,
202+
plugin=obj
203+
).get_bound_plugin()
204+
205+
if 'breakpoints' in container.glossary:
206+
breakpoints = container.glossary['breakpoints']
207+
elif 'media_queries' in container.glossary:
208+
#Case Jumbotron is first, its not has ancestor container
209+
breakpoints = list(container.glossary['media_queries'].keys())
209210

210211
width_fields, offset_fields, reorder_fields, responsive_fields = {}, {}, {}, {}
211212
units = [ngettext_lazy("{} unit", "{} units", i).format(i) for i in range(0, 13)]
@@ -334,9 +335,14 @@ class Meta:
334335
def save_model(self, request, obj, form, change):
335336
super().save_model(request, obj, form, change)
336337
obj.sanitize_children()
338+
if not CMS_:
339+
obj.sanitize_related_siblings()
340+
341+
def sanitize_related_siblings_model(self):
342+
self.sanitize_related_siblings()
337343

338344
@classmethod
339-
def sanitize_model(cls, obj):
345+
def sanitize_model(cls,obj):
340346
sanitized = super().sanitize_model(obj)
341347
return sanitized
342348

cmsplugin_cascade/bootstrap4/secondary_menu.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,11 @@
33
from django.utils.translation import gettext_lazy as _
44
from entangled.forms import EntangledModelFormMixin
55
from cms.plugin_pool import plugin_pool
6-
from cms.models.pagemodel import Page
6+
from cms.models import Page
7+
from cms.sitemaps import CMSSitemap
8+
from cmsplugin_cascade.utils_helpers import CMS_
79
from .plugin_base import BootstrapPluginBase
810

9-
1011
class SecondaryMenuFormMixin(EntangledModelFormMixin):
1112
page_id = ChoiceField(
1213
label=_("CMS Page Id"),
@@ -29,7 +30,11 @@ class Meta:
2930
entangled_fields = {'glossary': ['page_id', 'offset', 'limit']}
3031

3132
def __init__(self, *args, **kwargs):
32-
choices = [(p.reverse_id, str(p)) for p in Page.objects.filter(reverse_id__isnull=False, publisher_is_draft=False)]
33+
if CMS_:
34+
choices = [(p.reverse_id, str(p)) for p in Page.objects.filter(reverse_id__isnull=False, publisher_is_draft=False)]
35+
else:
36+
pages_id = [ p.id for p in CMSSitemap().items()]
37+
choices = [(p.reverse_id, str(p)) for p in Page.objects.filter(reverse_id__isnull=False).filter(id__in=pages_id)]
3338
self.base_fields['page_id'].choices = choices
3439
super().__init__(*args, **kwargs)
3540

cmsplugin_cascade/link/forms.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
from cms.utils import get_current_site
1414
from cms.models import Page
15+
from cmsplugin_cascade.utils_helpers import get_qs_pages_public
1516
from entangled.forms import EntangledModelFormMixin, get_related_object
1617
from filer.models.filemodels import File as FilerFileModel
1718
from filer.fields.file import AdminFileWidget, FilerFileField
@@ -54,7 +55,7 @@ class LinkSearchField(ModelChoiceField):
5455
widget = PageSelect2Widget()
5556

5657
def __init__(self, *args, **kwargs):
57-
queryset = Page.objects.public()
58+
queryset = get_qs_pages_public()
5859
try:
5960
queryset = queryset.published().on_site(get_current_site())
6061
except:

cmsplugin_cascade/link/settings.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+

cmsplugin_cascade/models_base.py

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
from cms.models import CMSPlugin
77
from cms.plugin_pool import plugin_pool
88
from cms.utils.placeholder import get_placeholder_conf
9-
9+
from cmsplugin_cascade.utils_helpers import CMS_
1010

1111
class CascadeModelBase(CMSPlugin):
1212
"""
@@ -60,9 +60,15 @@ def get_parent_instance(self):
6060
except model.DoesNotExist:
6161
continue
6262
# in case our plugin is the child of a TextPlugin, return its grandparent
63-
parent = self.get_parent()
63+
if CMS_:
64+
parent = self.get_parent()
65+
else:
66+
parent = self.parent
6467
if parent and parent.plugin_type == 'TextPlugin':
65-
grandparent_id = self.get_parent().parent_id
68+
if CMS_:
69+
grandparent_id = self.get_parent().parent_id
70+
else:
71+
grandparent_id = self.parent.parent_id
6672
for model in CascadeModelBase._get_cascade_elements():
6773
try:
6874
return model.objects.get(id=grandparent_id)
@@ -98,6 +104,17 @@ def get_num_children(self):
98104
"""
99105
return self.get_children().count()
100106

107+
def sanitize_related_siblings(self):
108+
"""
109+
Save relateds siblings depend save_model change inherited CMSPluginBase.
110+
"""
111+
if self.parent:
112+
plugins = self.__class__.objects.filter(id__in=self.parent._get_descendants_ids())
113+
for i in plugins:
114+
if i.plugin_class.require_parent or i.plugin_class.parent_classes:
115+
i.save()
116+
return True
117+
101118
def sanitize_children(self):
102119
"""
103120
Recursively walk down the plugin tree and invoke method ``save(sanitize_only=True)`` for
@@ -109,7 +126,7 @@ def sanitize_children(self):
109126
for child in children:
110127
child.save(sanitize_only=True)
111128
child.sanitize_children()
112-
129+
113130
@classmethod
114131
def from_db(cls, db, field_names, values):
115132
instance = cls(*values)
@@ -126,10 +143,15 @@ def save(self, sanitize_only=False, *args, **kwargs):
126143
sanitized = self.plugin_class.sanitize_model(self)
127144
if sanitize_only:
128145
if sanitized:
129-
super().save(no_signals=True)
146+
super().save()
130147
else:
131148
super().save(*args, **kwargs)
132149

150+
def delete(self, *args, **kwargs):
151+
super().delete( *args, **kwargs)
152+
if not CMS_:
153+
self.plugin_class.sanitize_related_siblings_model(self)
154+
133155
@classmethod
134156
def _get_cascade_elements(cls):
135157
"""
@@ -143,3 +165,4 @@ def _get_cascade_elements(cls):
143165
if issubclass(p.model, cls)])
144166
cls._cached_cascade_elements = cce
145167
return cls._cached_cascade_elements
168+

cmsplugin_cascade/plugin_base.py

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
from cms.plugin_base import CMSPluginBaseMetaclass, CMSPluginBase
99
from cms.utils.compat.dj import is_installed
1010
from cmsplugin_cascade import app_settings
11+
from cmsplugin_cascade.utils_helpers import get_prev_sibling
1112
from .mixins import CascadePluginMixin
1213
from .models_base import CascadeModelBase
1314
from .models import CascadeElement, SharableCascadeElement
@@ -272,7 +273,7 @@ def get_identifier(cls, instance):
272273
return SafeText()
273274

274275
@classmethod
275-
def sanitize_model(cls, instance):
276+
def sanitize_model(cls, instance,sanitize_related_sibling=None):
276277
"""
277278
This method is called, before the model is written to the database. It can be overloaded
278279
to sanitize the current models, in case a parent model changed in a way, which might
@@ -284,6 +285,17 @@ def sanitize_model(cls, instance):
284285
instance.glossary = {}
285286
return False
286287

288+
@classmethod
289+
def sanitize_related_siblings_model(cls, instance):
290+
"""
291+
This method is called, after the model is written to the database. It can be overloaded
292+
to sanitize the current related siblings models, in case a require_parent or parent_classes is in plugin,
293+
which might affect these related siblings plugin.
294+
This method shall return `True`, in case a model change was necessary, otherwise it shall
295+
return `False` to prevent a useless database update.
296+
"""
297+
return False
298+
287299
@classmethod
288300
def get_data_representation(cls, instance):
289301
"""
@@ -363,11 +375,9 @@ def get_previous_instance(self, obj):
363375
Return the previous plugin instance for the given object.
364376
This differs from `obj.get_prev_sibling()` which returns an unsorted sibling.
365377
"""
366-
ordered_siblings = obj.get_siblings().filter(placeholder=obj.placeholder).order_by('position')
367-
pos = list(ordered_siblings).index(obj.cmsplugin_ptr)
368-
if pos > 0:
369-
prev_sibling = ordered_siblings[pos - 1]
370-
return prev_sibling.get_bound_plugin()
378+
prev_sibling = get_prev_sibling(obj)
379+
if prev_sibling:
380+
return prev_sibling.get_bound_plugin()
371381

372382
def get_next_instance(self, obj):
373383
"""
@@ -405,3 +415,4 @@ def in_edit_mode(self, request, placeholder):
405415
if edit_mode:
406416
edit_mode = placeholder.has_change_permission(request.user)
407417
return edit_mode
418+

0 commit comments

Comments
 (0)