Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
b8f855c
setup.py:add django-cms 4
haricot Oct 15, 2020
2ca00a8
adaptation to DjangoCMS 4
haricot Oct 16, 2020
c24749e
Merge pull request #55 from jrief/master
haricot Oct 16, 2020
c976b24
Merge pull request #56 from haricot/master
haricot Oct 16, 2020
defa6d3
CMS4 testing matrix
haricot Oct 16, 2020
58eb628
Update admin.py
haricot Oct 16, 2020
04a2a8d
Update .travis.yml
haricot Oct 16, 2020
568e581
Update .travis.yml
haricot Oct 16, 2020
5f6fe38
Empty file cmsplugin_cascade/link/settings.py
haricot Oct 16, 2020
ef8a847
get_qs_pages_public:fix no such table: django_site
haricot Oct 17, 2020
8e0d328
add utils_helpers:get_plugins_as_layered_tree
haricot Oct 17, 2020
d28fd80
change version disto for update sqlite
haricot Oct 17, 2020
9ab5873
update .travis
haricot Oct 17, 2020
29aa890
update .travis
haricot Oct 17, 2020
a9b53c3
use get_placeholders if CMS4
haricot Oct 18, 2020
c685b2a
fix test use cms_page.languages
haricot Oct 18, 2020
5a04d7d
fix syntax
haricot Oct 18, 2020
6fc6298
fix cascade:CMSPlugin without MP_Node
haricot Oct 19, 2020
0618c65
update test_container, test_accordion
haricot Oct 20, 2020
37bdd31
wip update
haricot Oct 20, 2020
64c1f26
refactor get_ancestor plugin
haricot Oct 24, 2020
2e90289
update utils_helpers.py
haricot Oct 24, 2020
b854318
update utils_helpers.py, test_accordion.py
haricot Oct 24, 2020
c689b63
temporary change: reduce matrix test
haricot Oct 24, 2020
d616066
test_http:fix import order
haricot Oct 24, 2020
b18eeca
wip sanitize_related_siblings
haricot Oct 24, 2020
6dcc04f
Update utils_helpers.py
haricot Oct 24, 2020
b8c0101
Update bootstrap4/container.py
haricot Oct 24, 2020
3772058
Update utils_helpers.py
haricot Oct 24, 2020
ac2e974
fix OperationError:no such table: django_site
haricot Oct 24, 2020
e09fc49
fix OperationError:no such table: django_site
haricot Oct 24, 2020
56de8c0
fix OperationError:no such table: django_site
haricot Oct 24, 2020
d7dba70
wip update
haricot Oct 25, 2020
08c7a01
update bootstrap4/test_container.py
haricot Oct 25, 2020
e198b8e
update bootstrap4/test_container.py
haricot Oct 25, 2020
c7d64ad
update cmsplugin_cascade/utils_helpers.py
haricot Oct 25, 2020
ab29db6
update wip
haricot Oct 25, 2020
8a68e74
fix error: cms compatibity version
haricot Oct 25, 2020
71513f9
fix case jumbotron is first
haricot Oct 27, 2020
e76c7d5
wip update
haricot Oct 27, 2020
0f59a99
Add Internationalisation for bs4demo
haricot Oct 27, 2020
7d88fe0
update travis.yml
haricot Oct 28, 2020
d3295e7
fix import order
haricot Oct 28, 2020
3873118
fix import order
haricot Oct 28, 2020
0a96c76
Update pyproject.toml
haricot Oct 28, 2020
68f18d6
fix import Clipboard with cms4
haricot Oct 30, 2020
1859feb
Merge branch 'master' into experiment_cms4
haricot Oct 30, 2020
04c635e
Merge branch 'jrief:master' into master
haricot Jul 21, 2021
c11815e
branch update
haricot Jul 21, 2021
a032d0f
Update pyproject.toml
haricot Jul 21, 2021
d031b74
Update pyproject.toml
haricot Jul 21, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
dist: focal
language: python

python:
- 3.7
- 3.8
- 3.9

env:
- DJANGOVER=django31 CMSVER=cms40
- DJANGOVER=django31 CMSVER=cms38

install:
Expand Down
11 changes: 2 additions & 9 deletions cmsplugin_cascade/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,12 @@
from django.contrib import admin
from django.contrib.sites.shortcuts import get_current_site
from django.forms import Media, widgets
from django.db.models import Q
from django.http import JsonResponse, HttpResponseForbidden, HttpResponseNotFound
from django.urls import re_path, reverse
from django.utils.translation import get_language_from_request

from cms.models.pagemodel import Page
from cms.extensions import PageExtensionAdmin
from cms.utils.page import get_page_from_path
from cmsplugin_cascade.utils_helpers import get_page_from_path, get_matching_published_pages
from cmsplugin_cascade.models import CascadePage, IconFont
from cmsplugin_cascade.link.forms import format_page_link

Expand Down Expand Up @@ -80,12 +78,7 @@ def get_published_pagelist(self, request, *args, **kwargs):
return JsonResponse(data)

# otherwise resolve by search term
matching_published_pages = Page.objects.published().public().filter(
Q(title_set__title__icontains=query_term, title_set__language=language)
| Q(title_set__path__icontains=query_term, title_set__language=language)
| Q(title_set__menu_title__icontains=query_term, title_set__language=language)
| Q(title_set__page_title__icontains=query_term, title_set__language=language)
).distinct().order_by('title_set__title').iterator()
matching_published_pages = get_matching_published_pages(query_term,language)

for page in matching_published_pages:
data['results'].append(self.get_result_set(language, page))
Expand Down
35 changes: 27 additions & 8 deletions cmsplugin_cascade/bootstrap4/container.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@
from cmsplugin_cascade import app_settings
from cmsplugin_cascade.bootstrap4.grid import Breakpoint
from cmsplugin_cascade.forms import ManageChildrenFormMixin
from cmsplugin_cascade.utils_helpers import CMS_, get_ancestor
from .plugin_base import BootstrapPluginBase
from . import grid


def get_widget_choices():
breakpoints = app_settings.CMSPLUGIN_CASCADE['bootstrap4']['fluid_bounds']
widget_choices = []
Expand Down Expand Up @@ -105,6 +105,8 @@ def get_css_classes(cls, obj):
def save_model(self, request, obj, form, change):
super().save_model(request, obj, form, change)
obj.sanitize_children()
obj.sanitize_related_siblings()


plugin_pool.register_plugin(BootstrapContainerPlugin)

Expand All @@ -128,9 +130,8 @@ class Meta:
class RowGridMixin:
def get_grid_instance(self):
row = grid.Bootstrap4Row()
query = Q(plugin_type='BootstrapContainerPlugin') | Q(plugin_type='BootstrapColumnPlugin') \
| Q(plugin_type='BootstrapJumbotronPlugin')
container = self.get_ancestors().order_by('depth').filter(query).last().get_bound_plugin().get_grid_instance()
class_ancestor_name = ['BootstrapContainerPlugin', 'BootstrapColumnPlugin', 'BootstrapJumbotronPlugin']
container = get_ancestor( class_ancestor_name , plugin=self).get_bound_plugin().get_grid_instance()
container.add_row(row)
return row

Expand Down Expand Up @@ -162,11 +163,11 @@ class ColumnGridMixin:
'xs-column-offset', 'sm-column-offset', 'md-column-offset', 'lg-column-offset', 'xs-column-offset']
def get_grid_instance(self):
column = None
query = Q(plugin_type='BootstrapRowPlugin')
row_obj = self.get_ancestors().order_by('depth').filter(query).last().get_bound_plugin()
row_obj = get_ancestor(['BootstrapRowPlugin'], plugin=self).get_bound_plugin()
# column_siblings = row_obj.get_descendants().order_by('depth').filter(plugin_type='BootstrapColumnPlugin')
row = row_obj.get_grid_instance()
for column_sibling in self.get_siblings():
siblings = self.parent.get_children()
for column_sibling in siblings:
classes = [val for key, val in column_sibling.get_bound_plugin().glossary.items()
if key in self.valid_keys and val]
if column_sibling.pk == self.pk:
Expand Down Expand Up @@ -197,6 +198,18 @@ def choose_help_text(*phrases):
else:
return phrases[2]


container = get_ancestor(['BootstrapContainerPlugin','BootstrapJumbotronPlugin'],
_cms_initial_attributes=self._cms_initial_attributes,
plugin=obj
).get_bound_plugin()

if 'breakpoints' in container.glossary:
breakpoints = container.glossary['breakpoints']
elif 'media_queries' in container.glossary:
#Case Jumbotron is first, its not has ancestor container
breakpoints = list(container.glossary['media_queries'].keys())
"""
if 'parent' in self._cms_initial_attributes:
container=self._cms_initial_attributes['parent'].get_ancestors().order_by('depth').last().get_bound_plugin()
else:
Expand All @@ -207,6 +220,7 @@ def choose_help_text(*phrases):
jumbotrons=obj.get_ancestors().filter(plugin_type='BootstrapJumbotronPlugin')
container=jumbotrons.order_by('depth').last().get_bound_plugin()
breakpoints = container.glossary['breakpoints']
"""

width_fields, offset_fields, reorder_fields, responsive_fields = {}, {}, {}, {}
units = [ngettext_lazy("{} unit", "{} units", i).format(i) for i in range(0, 13)]
Expand Down Expand Up @@ -335,9 +349,14 @@ class Meta:
def save_model(self, request, obj, form, change):
super().save_model(request, obj, form, change)
obj.sanitize_children()
if not CMS_:
obj.sanitize_related_siblings()

def sanitize_related_siblings_model(self):
self.sanitize_related_siblings()

@classmethod
def sanitize_model(cls, obj):
def sanitize_model(cls,obj):
sanitized = super().sanitize_model(obj)
return sanitized

Expand Down
11 changes: 8 additions & 3 deletions cmsplugin_cascade/bootstrap4/secondary_menu.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@
from django.utils.translation import gettext_lazy as _
from entangled.forms import EntangledModelFormMixin
from cms.plugin_pool import plugin_pool
from cms.models.pagemodel import Page
from cms.models import Page
from cms.sitemaps import CMSSitemap
from cmsplugin_cascade.utils_helpers import CMS_
from .plugin_base import BootstrapPluginBase


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

def __init__(self, *args, **kwargs):
choices = [(p.reverse_id, str(p)) for p in Page.objects.filter(reverse_id__isnull=False, publisher_is_draft=False)]
if CMS_:
choices = [(p.reverse_id, str(p)) for p in Page.objects.filter(reverse_id__isnull=False, publisher_is_draft=False)]
else:
pages_id = [ p.id for p in CMSSitemap().items()]
choices = [(p.reverse_id, str(p)) for p in Page.objects.filter(reverse_id__isnull=False).filter(id__in=pages_id)]
self.base_fields['page_id'].choices = choices
super().__init__(*args, **kwargs)

Expand Down
33 changes: 24 additions & 9 deletions cmsplugin_cascade/clipboard/cms_plugins.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@
from cmsplugin_cascade.clipboard.forms import ClipboardBaseForm
from cmsplugin_cascade.clipboard.utils import deserialize_to_clipboard, serialize_from_placeholder
from cmsplugin_cascade.models import CascadeClipboard

from cmsplugin_cascade.utils_helpers import CMS_
from cms.utils.plugins import copy_plugins_to_placeholder

class CascadeClipboardPlugin(CMSPluginBase):
render_plugin = False
Expand Down Expand Up @@ -114,7 +115,10 @@ def paste_from_clipboard(self, request, form):
placeholder = form.cleaned_data['placeholder']
language = form.cleaned_data['language']
cascade_clipboard = form.cleaned_data['clipboard']
tree_order = placeholder.get_plugin_tree_order(language)
if CMS_:
tree_order = placeholder.get_plugin_tree_order(language)
else:
tree_order = list(placeholder.get_plugins().values_list('id', flat=True))
deserialize_to_clipboard(request, cascade_clipboard.data)
cascade_clipboard.last_accessed_at = now()
cascade_clipboard.save(update_fields=['last_accessed_at'])
Expand All @@ -123,13 +127,24 @@ def paste_from_clipboard(self, request, form):
cb_placeholder_plugin = request.toolbar.clipboard.cmsplugin_set.filter(plugin_type='PlaceholderPlugin').first()
cb_placeholder_instance, _ = cb_placeholder_plugin.get_plugin_instance()
new_plugins = cb_placeholder_instance.placeholder_ref.get_plugins()
new_plugins.update(placeholder=placeholder)

# reorder root plugins in placeholder
root_plugins = placeholder.get_plugins(language).filter(parent__isnull=True).order_by('changed_date')
for position, plugin in enumerate(root_plugins.iterator()):
plugin.update(position=position)
placeholder.mark_as_dirty(language, clear_cache=False)
if CMS_:
new_plugins.update(placeholder=placeholder)

# reorder root plugins in placeholder
root_plugins = placeholder.get_plugins(language).filter(parent__isnull=True).order_by('changed_date')
for position, plugin in enumerate(root_plugins.iterator()):
plugin.update(position=position)
placeholder.mark_as_dirty(language, clear_cache=False)
else:
last_plugin_position = placeholder.get_last_plugin_position(language)
last_plugin_position = last_plugin_position+1 if last_plugin_position else 1

copy_plugins_to_placeholder(
new_plugins,
placeholder=placeholder,
language=language,
start_positions={language: last_plugin_position},
)

# create a list of pasted plugins to be added to the structure view
all_plugins = placeholder.get_plugins(language)
Expand Down
5 changes: 4 additions & 1 deletion cmsplugin_cascade/link/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,11 @@

from cms.utils import get_current_site
from cms.models import Page

from cmsplugin_cascade.utils_helpers import get_qs_pages_public
from entangled.forms import EntangledModelFormMixin
from entangled.utils import get_related_object

from filer.models.filemodels import File as FilerFileModel
from filer.fields.file import AdminFileWidget, FilerFileField

Expand Down Expand Up @@ -54,7 +57,7 @@ class LinkSearchField(ModelChoiceField):
widget = PageSelect2Widget()

def __init__(self, *args, **kwargs):
queryset = Page.objects.public()
queryset = get_qs_pages_public()
try:
queryset = queryset.published().on_site(get_current_site()).distinct()
except:
Expand Down
1 change: 1 addition & 0 deletions cmsplugin_cascade/link/settings.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

31 changes: 27 additions & 4 deletions cmsplugin_cascade/models_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from cms.models import CMSPlugin
from cms.plugin_pool import plugin_pool
from cms.utils.placeholder import get_placeholder_conf

from cmsplugin_cascade.utils_helpers import CMS_

class CascadeModelBase(CMSPlugin):
"""
Expand Down Expand Up @@ -60,9 +60,15 @@ def get_parent_instance(self):
except model.DoesNotExist:
continue
# in case our plugin is the child of a TextPlugin, return its grandparent
parent = self.get_parent()
if CMS_:
parent = self.get_parent()
else:
parent = self.parent
if parent and parent.plugin_type == 'TextPlugin':
grandparent_id = self.get_parent().parent_id
if CMS_:
grandparent_id = self.get_parent().parent_id
else:
grandparent_id = self.parent.parent_id
for model in CascadeModelBase._get_cascade_elements():
try:
return model.objects.get(id=grandparent_id)
Expand Down Expand Up @@ -98,6 +104,17 @@ def get_num_children(self):
"""
return self.get_children().count()

def sanitize_related_siblings(self):
"""
Save relateds siblings depend save_model change inherited CMSPluginBase.
"""
if self.parent:
plugins = self.__class__.objects.filter(id__in=self.parent._get_descendants_ids())
for i in plugins:
if i.plugin_class.require_parent or i.plugin_class.parent_classes:
i.save()
return True

def sanitize_children(self):
"""
Recursively walk down the plugin tree and invoke method ``save(sanitize_only=True)`` for
Expand Down Expand Up @@ -126,10 +143,15 @@ def save(self, sanitize_only=False, *args, **kwargs):
sanitized = self.plugin_class.sanitize_model(self)
if sanitize_only:
if sanitized:
super().save(no_signals=True)
super().save()
else:
super().save(*args, **kwargs)

def delete(self, *args, **kwargs):
super().delete( *args, **kwargs)
if not CMS_:
self.plugin_class.sanitize_related_siblings_model(self)

@classmethod
def _get_cascade_elements(cls):
"""
Expand All @@ -143,3 +165,4 @@ def _get_cascade_elements(cls):
if issubclass(p.model, cls)])
cls._cached_cascade_elements = cce
return cls._cached_cascade_elements

23 changes: 17 additions & 6 deletions cmsplugin_cascade/plugin_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from cms.plugin_base import CMSPluginBaseMetaclass, CMSPluginBase
from cms.utils.compat.dj import is_installed
from cmsplugin_cascade import app_settings
from cmsplugin_cascade.utils_helpers import get_prev_sibling
from .mixins import CascadePluginMixin
from .models_base import CascadeModelBase
from .models import CascadeElement, SharableCascadeElement
Expand Down Expand Up @@ -274,7 +275,7 @@ def get_identifier(cls, instance):
return SafeText()

@classmethod
def sanitize_model(cls, instance):
def sanitize_model(cls, instance,sanitize_related_sibling=None):
"""
This method is called, before the model is written to the database. It can be overloaded
to sanitize the current models, in case a parent model changed in a way, which might
Expand All @@ -286,6 +287,17 @@ def sanitize_model(cls, instance):
instance.glossary = {}
return False

@classmethod
def sanitize_related_siblings_model(cls, instance):
"""
This method is called, after the model is written to the database. It can be overloaded
to sanitize the current related siblings models, in case a require_parent or parent_classes is in plugin,
which might affect these related siblings plugin.
This method shall return `True`, in case a model change was necessary, otherwise it shall
return `False` to prevent a useless database update.
"""
return False

@classmethod
def get_data_representation(cls, instance):
"""
Expand Down Expand Up @@ -365,11 +377,9 @@ def get_previous_instance(self, obj):
Return the previous plugin instance for the given object.
This differs from `obj.get_prev_sibling()` which returns an unsorted sibling.
"""
ordered_siblings = obj.get_siblings().filter(placeholder=obj.placeholder).order_by('position')
pos = list(ordered_siblings).index(obj.cmsplugin_ptr)
if pos > 0:
prev_sibling = ordered_siblings[pos - 1]
return prev_sibling.get_bound_plugin()
prev_sibling = get_prev_sibling(obj)
if prev_sibling:
return prev_sibling.get_bound_plugin()

def get_next_instance(self, obj):
"""
Expand Down Expand Up @@ -408,3 +418,4 @@ def in_edit_mode(self, request, placeholder):
if edit_mode:
edit_mode = placeholder.has_change_permission(request.user)
return edit_mode

Loading