From 6124477236686ea8ee2f84630cf0fc04bde12acc Mon Sep 17 00:00:00 2001 From: Adrien Delhorme Date: Tue, 23 Apr 2024 16:38:15 +0200 Subject: [PATCH 1/4] Django 3 compatibility --- djangocms_conditional/cms_plugins.py | 4 ++-- djangocms_conditional/models.py | 14 ++++++-------- docs/conf.py | 16 ++++++++-------- tests/test_models.py | 6 +++--- 4 files changed, 19 insertions(+), 21 deletions(-) diff --git a/djangocms_conditional/cms_plugins.py b/djangocms_conditional/cms_plugins.py index 726646c..5533392 100644 --- a/djangocms_conditional/cms_plugins.py +++ b/djangocms_conditional/cms_plugins.py @@ -2,14 +2,14 @@ from cms.plugin_base import CMSPluginBase from cms.plugin_pool import plugin_pool from django.contrib.auth.models import User, AnonymousUser -from django.utils.translation import ugettext_lazy as _ +from django.utils.translation import gettext_lazy as _ from .models import ConditionalPluginModel, MODE_IN_GROUP, MODE_NOT_IN_GROUP, MODE_NOT_IN_GROUP_PLUS_ANON, \ MODE_ANONYMOUS class ConditionalContainerPlugin(CMSPluginBase): - name = _(u'Conditional content') + name = _('Conditional content') model = ConditionalPluginModel allow_children = True cache = False diff --git a/djangocms_conditional/models.py b/djangocms_conditional/models.py index a6abbcc..c29501d 100644 --- a/djangocms_conditional/models.py +++ b/djangocms_conditional/models.py @@ -2,8 +2,7 @@ from cms.models import CMSPlugin from django.contrib.auth.models import Group from django.db import models -from django.utils.encoding import python_2_unicode_compatible -from django.utils.translation import ugettext_lazy as _ +from django.utils.translation import gettext_lazy as _ MODE_IN_GROUP = 'in_group' @@ -12,21 +11,20 @@ MODE_ANONYMOUS = 'anonymous' -@python_2_unicode_compatible class ConditionalPluginModel(CMSPlugin): - permitted_group = models.ForeignKey(Group, null=False, blank=False) + permitted_group = models.ForeignKey(Group, null=False, blank=False, on_delete=models.CASCADE) mode = models.CharField(max_length=40, default='in_group', - help_text=_(u"Conditional access type"), - choices=((MODE_IN_GROUP, _(u'Users in group')), - (MODE_NOT_IN_GROUP, _(u'Users not in group')), + help_text=_("Conditional access type"), + choices=((MODE_IN_GROUP, _('Users in group')), + (MODE_NOT_IN_GROUP, _('Users not in group')), (MODE_NOT_IN_GROUP_PLUS_ANON, _('Anonymous users and users not in group')), (MODE_ANONYMOUS, _('Anonymous users')), )) def __str__(self): - return _(u'Conditional access %s group="%s"') % ( + return _('Conditional access %s group="%s"') % ( self.mode, self.permitted_group.name, ) diff --git a/docs/conf.py b/docs/conf.py index 555338e..42e97bc 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -46,8 +46,8 @@ master_doc = 'index' # General information about the project. -project = u'djangocms-conditional' -copyright = u'2017, Roy Hooper' +project = 'djangocms-conditional' +copyright = '2017, Roy Hooper' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the @@ -192,8 +192,8 @@ # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, author, documentclass [howto/manual]). latex_documents = [ - ('index', 'djangocms-conditional.tex', u'djangocms-conditional Documentation', - u'Iacopo Spalletti', 'manual'), + ('index', 'djangocms-conditional.tex', 'djangocms-conditional Documentation', + 'Iacopo Spalletti', 'manual'), ] # The name of an image file (relative to this directory) to place at the top of @@ -222,8 +222,8 @@ # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). man_pages = [ - ('index', 'djangocms-conditional', u'djangocms-conditional Documentation', - [u'Iacopo Spalletti'], 1) + ('index', 'djangocms-conditional', 'djangocms-conditional Documentation', + ['Iacopo Spalletti'], 1) ] # If true, show URL addresses after external links. @@ -236,8 +236,8 @@ # (source start file, target name, title, author, # dir menu entry, description, category) texinfo_documents = [ - ('index', 'djangocms-conditional', u'djangocms-conditional Documentation', - u'Iacopo Spalletti', 'djangocms-conditional', 'One line description of project.', + ('index', 'djangocms-conditional', 'djangocms-conditional Documentation', + 'Iacopo Spalletti', 'djangocms-conditional', 'One line description of project.', 'Miscellaneous'), ] diff --git a/tests/test_models.py b/tests/test_models.py index 4793620..05a971e 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -24,14 +24,14 @@ def setup_plugin(self, group, mode='in_group'): parent_plugin = add_plugin( placeholder, ConditionalContainerPlugin, - u'en', + 'en', permitted_group=group, mode=mode ) parent_plugin.save() - text_content = u"Child plugin" - text_plugin = add_plugin(placeholder, u"TextPlugin", u"en", body=text_content, target=parent_plugin,) + text_content = "Child plugin" + text_plugin = add_plugin(placeholder, "TextPlugin", "en", body=text_content, target=parent_plugin,) text_plugin.save() parent_plugin.child_plugin_instances = [text_plugin] From a5ad5c142dac9a2325f485f54f29320426adf55e Mon Sep 17 00:00:00 2001 From: Adrien Delhorme Date: Tue, 23 Apr 2024 16:41:39 +0200 Subject: [PATCH 2/4] fix user.is_anonymous is a property not a method --- djangocms_conditional/cms_plugins.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/djangocms_conditional/cms_plugins.py b/djangocms_conditional/cms_plugins.py index 5533392..143cca6 100644 --- a/djangocms_conditional/cms_plugins.py +++ b/djangocms_conditional/cms_plugins.py @@ -31,13 +31,13 @@ def render(self, context, instance, placeholder): if user.groups.filter(id=instance.permitted_group.id).exists(): context['instance'] = instance elif instance.mode == MODE_NOT_IN_GROUP: - if not (user.is_anonymous() or user.groups.filter(id=instance.permitted_group.id).exists()): + if not (user.is_anonymous or user.groups.filter(id=instance.permitted_group.id).exists()): context['instance'] = instance elif instance.mode == MODE_ANONYMOUS: - if user.is_anonymous(): + if user.is_anonymous: context['instance'] = instance elif instance.mode == MODE_NOT_IN_GROUP_PLUS_ANON: - if user.is_anonymous() or not user.groups.filter(id=instance.permitted_group.id).exists(): + if user.is_anonymous or not user.groups.filter(id=instance.permitted_group.id).exists(): context['instance'] = instance return context From 4d7944d6d1c7c057c22a13422297051e87b67c76 Mon Sep 17 00:00:00 2001 From: Adrien Delhorme Date: Tue, 23 Apr 2024 16:43:48 +0200 Subject: [PATCH 3/4] allow superusers to see all contents --- djangocms_conditional/cms_plugins.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/djangocms_conditional/cms_plugins.py b/djangocms_conditional/cms_plugins.py index 143cca6..60c4a91 100644 --- a/djangocms_conditional/cms_plugins.py +++ b/djangocms_conditional/cms_plugins.py @@ -27,7 +27,9 @@ def render(self, context, instance, placeholder): user = AnonymousUser() # Should never happen # This could be coded more efficiently, but is this way for clarity - if instance.mode == MODE_IN_GROUP: + if user.is_superuser: + context['instance'] = instance + elif instance.mode == MODE_IN_GROUP: if user.groups.filter(id=instance.permitted_group.id).exists(): context['instance'] = instance elif instance.mode == MODE_NOT_IN_GROUP: From 80e3f83324107f63700b4535fcda8763f95b37e5 Mon Sep 17 00:00:00 2001 From: Adrien Delhorme Date: Tue, 23 Apr 2024 17:08:55 +0200 Subject: [PATCH 4/4] permitted group is optional --- djangocms_conditional/cms_plugins.py | 2 + djangocms_conditional/forms.py | 20 +++++++ ...ionalpluginmodel_cmsplugin_ptr_and_more.py | 53 +++++++++++++++++++ djangocms_conditional/models.py | 13 +++-- 4 files changed, 83 insertions(+), 5 deletions(-) create mode 100644 djangocms_conditional/forms.py create mode 100644 djangocms_conditional/migrations/0003_alter_conditionalpluginmodel_cmsplugin_ptr_and_more.py diff --git a/djangocms_conditional/cms_plugins.py b/djangocms_conditional/cms_plugins.py index 60c4a91..4bbd4d2 100644 --- a/djangocms_conditional/cms_plugins.py +++ b/djangocms_conditional/cms_plugins.py @@ -6,11 +6,13 @@ from .models import ConditionalPluginModel, MODE_IN_GROUP, MODE_NOT_IN_GROUP, MODE_NOT_IN_GROUP_PLUS_ANON, \ MODE_ANONYMOUS +from .forms import ConditionalPluginForm class ConditionalContainerPlugin(CMSPluginBase): name = _('Conditional content') model = ConditionalPluginModel + form = ConditionalPluginForm allow_children = True cache = False render_template = 'djangocms_conditional/conditional.html' diff --git a/djangocms_conditional/forms.py b/djangocms_conditional/forms.py new file mode 100644 index 0000000..d280407 --- /dev/null +++ b/djangocms_conditional/forms.py @@ -0,0 +1,20 @@ +from django import forms +from django.utils.translation import gettext as _ +from .models import MODE_IN_GROUP, MODE_NOT_IN_GROUP, MODE_NOT_IN_GROUP_PLUS_ANON + + +class ConditionalPluginForm(forms.ModelForm): + fields = "__all__" + + def clean(self): + cleaned_data = super().clean() + permitted_group = cleaned_data.get("permitted_group") + mode = cleaned_data.get("mode") + modes_that_require_group = [ + MODE_IN_GROUP, + MODE_NOT_IN_GROUP, + MODE_NOT_IN_GROUP_PLUS_ANON + ] + + if mode in modes_that_require_group and permitted_group is None: + self.add_error("permitted_group", _("You must choose a group when using this mode.")) diff --git a/djangocms_conditional/migrations/0003_alter_conditionalpluginmodel_cmsplugin_ptr_and_more.py b/djangocms_conditional/migrations/0003_alter_conditionalpluginmodel_cmsplugin_ptr_and_more.py new file mode 100644 index 0000000..e0c1c32 --- /dev/null +++ b/djangocms_conditional/migrations/0003_alter_conditionalpluginmodel_cmsplugin_ptr_and_more.py @@ -0,0 +1,53 @@ +# Generated by Django 4.2.11 on 2024-04-23 14:49 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + dependencies = [ + ("auth", "0012_alter_user_first_name_max_length"), + ("cms", "0022_auto_20180620_1551"), + ("djangocms_conditional", "0002_conditionalpluginmodel_mode"), + ] + + operations = [ + migrations.AlterField( + model_name="conditionalpluginmodel", + name="cmsplugin_ptr", + field=models.OneToOneField( + auto_created=True, + on_delete=django.db.models.deletion.CASCADE, + parent_link=True, + primary_key=True, + related_name="%(app_label)s_%(class)s", + serialize=False, + to="cms.cmsplugin", + ), + ), + migrations.AlterField( + model_name="conditionalpluginmodel", + name="mode", + field=models.CharField( + choices=[ + ("in_group", "Users in group"), + ("not_in_group", "Users not in group"), + ( + "not_in_group_plus_anon", + "Anonymous users and users not in group", + ), + ("anonymous", "Anonymous users"), + ], + default="in_group", + help_text="Conditional access type", + max_length=40, + ), + ), + migrations.AlterField( + model_name="conditionalpluginmodel", + name="permitted_group", + field=models.ForeignKey( + null=True, blank=True, on_delete=django.db.models.deletion.SET_NULL, to="auth.group" + ), + ), + ] diff --git a/djangocms_conditional/models.py b/djangocms_conditional/models.py index c29501d..b720b52 100644 --- a/djangocms_conditional/models.py +++ b/djangocms_conditional/models.py @@ -13,7 +13,7 @@ class ConditionalPluginModel(CMSPlugin): - permitted_group = models.ForeignKey(Group, null=False, blank=False, on_delete=models.CASCADE) + permitted_group = models.ForeignKey(Group, null=True, blank=True, on_delete=models.SET_NULL) mode = models.CharField(max_length=40, default='in_group', help_text=_("Conditional access type"), @@ -24,7 +24,10 @@ class ConditionalPluginModel(CMSPlugin): )) def __str__(self): - return _('Conditional access %s group="%s"') % ( - self.mode, - self.permitted_group.name, - ) + if self.permitted_group is not None: + return _('%s: %s') % ( + self.get_mode_display(), + self.permitted_group.name, + ) + else: + return self.get_mode_display()