From 6368d7ee4d89907ac025a00ce13dde9ee185b34a Mon Sep 17 00:00:00 2001 From: Adam Murray Date: Mon, 9 Aug 2021 13:12:27 +0100 Subject: [PATCH 001/107] Added cms_config versionable item and grouper --- djangocms_snippet/cms_config.py | 17 +++++++++++++++++ djangocms_snippet/models.py | 8 ++++++++ tests/requirements/dj22_cms40.txt | 0 3 files changed, 25 insertions(+) create mode 100644 djangocms_snippet/cms_config.py create mode 100644 tests/requirements/dj22_cms40.txt diff --git a/djangocms_snippet/cms_config.py b/djangocms_snippet/cms_config.py new file mode 100644 index 00000000..a233b105 --- /dev/null +++ b/djangocms_snippet/cms_config.py @@ -0,0 +1,17 @@ +from cms.app_base import CMSAppConfig, CMSAppExtension + +from djangocms_versioning.datastructures import VersionableItem, default_copy + +from .models import Snippet + + +class SnippetCMSAppConfig(CMSAppConfig): + djangocms_versioning_enabled = True + + versioning = [ + VersionableItem( + content_model=Snippet, + grouper_field_name="snippet_grouper", + copy_function=default_copy, + ) + ] diff --git a/djangocms_snippet/models.py b/djangocms_snippet/models.py index 23f27144..c3ebf52f 100644 --- a/djangocms_snippet/models.py +++ b/djangocms_snippet/models.py @@ -9,6 +9,10 @@ SEARCH_ENABLED = getattr(settings, 'DJANGOCMS_SNIPPET_SEARCH', False) +class SnippetGrouper(models.Model): + pass + + # Stores the actual data class Snippet(models.Model): """ @@ -19,6 +23,10 @@ class Snippet(models.Model): unique=True, max_length=255, ) + snippet_grouper = models.ForeignKey( + SnippetGrouper, + on_delete=models.PROTECT, + ) html = models.TextField( verbose_name=_('HTML'), blank=True, diff --git a/tests/requirements/dj22_cms40.txt b/tests/requirements/dj22_cms40.txt new file mode 100644 index 00000000..e69de29b From 75449d69ba2454bc19718ffdc55e4e20a8f14d0c Mon Sep 17 00:00:00 2001 From: Adam Murray Date: Mon, 9 Aug 2021 15:16:51 +0100 Subject: [PATCH 002/107] Added admin, requirements for testing and requirements for running --- djangocms_snippet/admin.py | 7 ++++++- setup.py | 2 +- tests/requirements/dj22_cms40.txt | 5 +++++ 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/djangocms_snippet/admin.py b/djangocms_snippet/admin.py index 9187fadd..22c889c4 100644 --- a/djangocms_snippet/admin.py +++ b/djangocms_snippet/admin.py @@ -3,7 +3,7 @@ from django.db import models from django.forms import Textarea -from .models import Snippet +from .models import Snippet, SnippetGrouper class SnippetAdmin(admin.ModelAdmin): @@ -23,4 +23,9 @@ class SnippetAdmin(admin.ModelAdmin): } +class SnippetGrouperAdmin(admin.ModelAdmin): + pass + + +admin.site.register(SnippetGrouper, SnippetGrouperAdmin) admin.site.register(Snippet, SnippetAdmin) diff --git a/setup.py b/setup.py index 9e41005e..d623eb77 100644 --- a/setup.py +++ b/setup.py @@ -5,7 +5,7 @@ REQUIREMENTS = [ - 'django-cms>=3.7', + 'django-cms>4.0', 'django-treebeard>=4.3,<4.5', ] diff --git a/tests/requirements/dj22_cms40.txt b/tests/requirements/dj22_cms40.txt index e69de29b..c84c4174 100644 --- a/tests/requirements/dj22_cms40.txt +++ b/tests/requirements/dj22_cms40.txt @@ -0,0 +1,5 @@ +-r base.txt + +Django>=2.2,<3.0 +https://github.com/django-cms/django-cms/tarball/release/4.0.x#egg=django-cms +https://github.com/divio/djangocms-versioning/tarball/master/#egg=djangocms-versioning From 9bc367c1a3a14c2785ae3ab5f16d2bb317e83553 Mon Sep 17 00:00:00 2001 From: Adam Murray Date: Wed, 11 Aug 2021 15:34:14 +0100 Subject: [PATCH 003/107] Update --- djangocms_snippet/admin.py | 7 +------ djangocms_snippet/models.py | 1 + 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/djangocms_snippet/admin.py b/djangocms_snippet/admin.py index 22c889c4..9187fadd 100644 --- a/djangocms_snippet/admin.py +++ b/djangocms_snippet/admin.py @@ -3,7 +3,7 @@ from django.db import models from django.forms import Textarea -from .models import Snippet, SnippetGrouper +from .models import Snippet class SnippetAdmin(admin.ModelAdmin): @@ -23,9 +23,4 @@ class SnippetAdmin(admin.ModelAdmin): } -class SnippetGrouperAdmin(admin.ModelAdmin): - pass - - -admin.site.register(SnippetGrouper, SnippetGrouperAdmin) admin.site.register(Snippet, SnippetAdmin) diff --git a/djangocms_snippet/models.py b/djangocms_snippet/models.py index c3ebf52f..e1c65280 100644 --- a/djangocms_snippet/models.py +++ b/djangocms_snippet/models.py @@ -26,6 +26,7 @@ class Snippet(models.Model): snippet_grouper = models.ForeignKey( SnippetGrouper, on_delete=models.PROTECT, + null=True, ) html = models.TextField( verbose_name=_('HTML'), From 7c9455cc4649a6d473365fb2698ad0b85c5d4e20 Mon Sep 17 00:00:00 2001 From: Adam Murray Date: Wed, 11 Aug 2021 15:43:23 +0100 Subject: [PATCH 004/107] Fixed issue in setup.py and added basic first migration --- .../migrations/0009_auto_20210811_0942.py | 25 +++++++++++++++++++ setup.py | 2 +- 2 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 djangocms_snippet/migrations/0009_auto_20210811_0942.py diff --git a/djangocms_snippet/migrations/0009_auto_20210811_0942.py b/djangocms_snippet/migrations/0009_auto_20210811_0942.py new file mode 100644 index 00000000..4f7e5cb8 --- /dev/null +++ b/djangocms_snippet/migrations/0009_auto_20210811_0942.py @@ -0,0 +1,25 @@ +# Generated by Django 2.2.24 on 2021-08-11 09:42 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('djangocms_snippet', '0008_auto_change_name'), + ] + + operations = [ + migrations.CreateModel( + name='SnippetGrouper', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ], + ), + migrations.AddField( + model_name='snippet', + name='snippet_grouper', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, to='djangocms_snippet.SnippetGrouper'), + ), + ] diff --git a/setup.py b/setup.py index d623eb77..566bc2cb 100644 --- a/setup.py +++ b/setup.py @@ -5,7 +5,7 @@ REQUIREMENTS = [ - 'django-cms>4.0', + 'django-cms', 'django-treebeard>=4.3,<4.5', ] From 4954ee42bcfa08e9d279637f6434114c78f844bd Mon Sep 17 00:00:00 2001 From: Adam Murray Date: Thu, 12 Aug 2021 14:41:35 +0100 Subject: [PATCH 005/107] Added migration to cms4 --- .../migrations/0010_migration_assign_grouper_field.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 djangocms_snippet/migrations/0010_migration_assign_grouper_field.py diff --git a/djangocms_snippet/migrations/0010_migration_assign_grouper_field.py b/djangocms_snippet/migrations/0010_migration_assign_grouper_field.py new file mode 100644 index 00000000..e69de29b From 8defe7f3a8214d3c044af5372ca6f5bd4cc0bc7a Mon Sep 17 00:00:00 2001 From: Adam Murray Date: Thu, 12 Aug 2021 14:41:57 +0100 Subject: [PATCH 006/107] Added migration to cms4 --- .../0010_migration_assign_grouper_field.py | 61 +++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/djangocms_snippet/migrations/0010_migration_assign_grouper_field.py b/djangocms_snippet/migrations/0010_migration_assign_grouper_field.py index e69de29b..c056a77c 100644 --- a/djangocms_snippet/migrations/0010_migration_assign_grouper_field.py +++ b/djangocms_snippet/migrations/0010_migration_assign_grouper_field.py @@ -0,0 +1,61 @@ +import logging + +from django.conf import settings +from django.db import migrations + +from djangocms_versioning.constants import DRAFT + +logger = logging.getLogger(__name__) + + +def forwards(apps, schema_editor): + db_alias = schema_editor.connection.alias + # Get the models required for the data migration + SnippetModel = apps.get_model('djangocms_snippet', 'Snippet') + SnippetGrouperModel = apps.get_model('djangocms_snippet', 'SnippetGrouper') + Version = apps.get_model('djangocms_versioning', 'Version') + User = apps.get_model(*settings.AUTH_USER_MODEL.split('.')) + ContentType = apps.get_model('contenttypes', 'ContentType') + + # The queryset of populate models. + queryset = SnippetModel.objects.all() + # The contenttype of the content model + snippet_contenttype = ContentType.objects.get(app_label='djangocms_snippet', model='snippet') + + def _create_version(snippet, state=DRAFT, number=1): + # Get a migration user. + migration_user = getattr(settings, "DJANGOCMS_SNIPPET_VERSIONING_MIGRATION_USER_ID", None) + if not migration_user: + logger.warning( + "Setting DJANGOCMS_SNIPPET_VERSIONING_MIGRATION_USER_ID not provided, defaulting to user id: 1" + ) + migration_user = User.objects.get(id=1) + + logger.info("Creating version for new grouper: {}".format(snippet.pk)) + + # Create a new version for the snippet + Version.objects.using(db_alias).create( + created_by=migration_user, + state=state, + number=number, + object_id=snippet.pk, + content_type=snippet_contenttype, + ) + + # Iterate over the queryset, create a grouper for each instance and map the content objects foreign key field to it. + for snippet in queryset: + grouper = SnippetGrouperModel.objects.create() + snippet.snippet_grouper = grouper + snippet.save() + _create_version(snippet) + + +class Migration(migrations.Migration): + + dependencies = [ + ('djangocms_snippet', '0009_auto_20210811_0942'), + ] + + operations = [ + migrations.RunPython(forwards) + ] From b9f822ff5b96bad56a547fd2bd1ae8df762bfe54 Mon Sep 17 00:00:00 2001 From: Adam Murray Date: Mon, 16 Aug 2021 11:33:35 +0100 Subject: [PATCH 007/107] Began to implement versioning switch, added migration as part of management command for cms3-cms4 --- djangocms_snippet/cms_config.py | 20 ++++--- djangocms_snippet/cms_plugins.py | 23 ++++++-- djangocms_snippet/management/__init__.py | 0 .../management/cms4_data_migration.py | 57 +++++++++++++++++++ djangocms_snippet/models.py | 25 +++++--- djangocms_snippet/utils.py | 10 ++++ 6 files changed, 113 insertions(+), 22 deletions(-) create mode 100644 djangocms_snippet/management/__init__.py create mode 100644 djangocms_snippet/management/cms4_data_migration.py create mode 100644 djangocms_snippet/utils.py diff --git a/djangocms_snippet/cms_config.py b/djangocms_snippet/cms_config.py index a233b105..6b7bb65b 100644 --- a/djangocms_snippet/cms_config.py +++ b/djangocms_snippet/cms_config.py @@ -1,17 +1,21 @@ from cms.app_base import CMSAppConfig, CMSAppExtension +from django.conf import settings + from djangocms_versioning.datastructures import VersionableItem, default_copy from .models import Snippet class SnippetCMSAppConfig(CMSAppConfig): - djangocms_versioning_enabled = True + djangocms_versioning_enabled = getattr( + settings, 'VERSIONING_ALIAS_MODELS_ENABLED', True) - versioning = [ - VersionableItem( - content_model=Snippet, - grouper_field_name="snippet_grouper", - copy_function=default_copy, - ) - ] + if djangocms_versioning_enabled: + versioning = [ + VersionableItem( + content_model=Snippet, + grouper_field_name="snippet_grouper", + copy_function=default_copy, + ) + ] diff --git a/djangocms_snippet/cms_plugins.py b/djangocms_snippet/cms_plugins.py index bf432da9..48da0f9e 100644 --- a/djangocms_snippet/cms_plugins.py +++ b/djangocms_snippet/cms_plugins.py @@ -7,14 +7,16 @@ from cms.plugin_base import CMSPluginBase from cms.plugin_pool import plugin_pool -from .models import SnippetPtr - +from .models import SnippetPluginModel, SnippetPtr +from .utils import is_versioning_enabled CACHE_ENABLED = getattr(settings, "DJANGOCMS_SNIPPET_CACHE", False) -class SnippetPlugin(CMSPluginBase): - model = SnippetPtr +class AbstractSnippetPlugin(CMSPluginBase): + class Meta: + abstract = True + name = _("Snippet") render_template = "djangocms_snippet/snippet.html" text_enabled = True @@ -51,4 +53,15 @@ def render(self, context, instance, placeholder): return context -plugin_pool.register_plugin(SnippetPlugin) +class SnippetPlugin(AbstractSnippetPlugin): + model = SnippetPtr + + +class VersionedSnippetPlugin(AbstractSnippetPlugin): + model = SnippetPluginModel + + +if is_versioning_enabled: + plugin_pool.register_plugin(VersionedSnippetPlugin) +else: + plugin_pool.register_plugin(SnippetPlugin) diff --git a/djangocms_snippet/management/__init__.py b/djangocms_snippet/management/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/djangocms_snippet/management/cms4_data_migration.py b/djangocms_snippet/management/cms4_data_migration.py new file mode 100644 index 00000000..78c5aa3a --- /dev/null +++ b/djangocms_snippet/management/cms4_data_migration.py @@ -0,0 +1,57 @@ +import logging + +from django.core.management.base import BaseCommand, CommandError + +from django.conf import settings +from django.contrib.auth.models import User +from django.contrib.contenttypes.models import ContentType + +from djangocms_versioning.models import Version + +from djangocms_snippet.models import Snippet, SnippetGrouper + +from djangocms_versioning.constants import DRAFT + + +logger = logging.getLogger(__name__) + + +class Command(BaseCommand): + help = 'Command to migrate cms3 model structure into cms4 by creating relevant Groupers and Versions' + + def _create_version(snippet, state=DRAFT, number=1): + # Get a migration user. + migration_user = getattr(settings, "DJANGOCMS_SNIPPET_VERSIONING_MIGRATION_USER_ID", None) + # The contenttype of the content model + snippet_contenttype = ContentType.objects.get(app_label='djangocms_snippet', model='snippet') + + if not migration_user: + logger.warning( + "Setting DJANGOCMS_SNIPPET_VERSIONING_MIGRATION_USER_ID not provided, defaulting to user id: 1" + ) + migration_user = User.objects.get(id=1) + + logger.info("Creating version for new grouper: {}".format(snippet.pk)) + + # Create a new version for the snippet + Version.objects.create( + created_by=migration_user, + state=state, + number=number, + object_id=snippet.pk, + content_type=snippet_contenttype, + ) + + def handle(self, *args, **options): + # The queryset of populate models. + queryset = Snippet.objects.all() + + # Iterate over the queryset, create a grouper for each instance + # and map the content objects foreign key field to it. + for snippet in queryset: + if not snippet.snippet_grouper: + grouper = SnippetGrouper.objects.create() + snippet.snippet_grouper = grouper + snippet.save() + if not snippet.versions.all(): + self._create_version(snippet) diff --git a/djangocms_snippet/models.py b/djangocms_snippet/models.py index e1c65280..7e6f8d7d 100644 --- a/djangocms_snippet/models.py +++ b/djangocms_snippet/models.py @@ -60,26 +60,33 @@ class Meta: # Plugin model - just a pointer to Snippet -class SnippetPtr(CMSPlugin): +class AbstractSnippetPluginModel(CMSPlugin): # Add an app namespace to related_name to avoid field name clashes # with any other plugins that have a field with the same name as the # lowercase of the class name of this model. # https://github.com/divio/django-cms/issues/5030 - cmsplugin_ptr = models.OneToOneField( - CMSPlugin, - related_name='%(app_label)s_%(class)s', - parent_link=True, - on_delete=models.CASCADE, - ) - - snippet = models.ForeignKey(Snippet, on_delete=models.CASCADE,) search_fields = ['snippet__html'] if SEARCH_ENABLED else [] class Meta: verbose_name = _('Snippet Ptr') verbose_name_plural = _('Snippet Ptrs') + abstract = True def __str__(self): # Return the referenced snippet's name rather than the default (ID #) return self.snippet.name + + +class SnippetPluginModel(AbstractSnippetPluginModel): + snippet = models.ForeignKey(SnippetGrouper, on_delete=models.CASCADE, ) + + +class SnippetPtr(AbstractSnippetPluginModel): + cmsplugin_ptr = models.OneToOneField( + CMSPlugin, + related_name='%(app_label)s_%(class)s', + parent_link=True, + on_delete=models.CASCADE, + ) + snippet = models.ForeignKey(Snippet, on_delete=models.CASCADE) diff --git a/djangocms_snippet/utils.py b/djangocms_snippet/utils.py new file mode 100644 index 00000000..91f48a2f --- /dev/null +++ b/djangocms_snippet/utils.py @@ -0,0 +1,10 @@ +from django.apps import apps + + +def is_versioning_enabled(): + from .models import Snippet + try: + app_config = apps.get_app_config('djangocms_versioning') + return app_config.cms_extension.is_content_model_versioned(Snippet) + except LookupError: + return False From 49e4bb3dd3dcad694bc7fd1517f2ad3fecd80f47 Mon Sep 17 00:00:00 2001 From: Adam Murray Date: Mon, 16 Aug 2021 11:48:21 +0100 Subject: [PATCH 008/107] Moved data migration to management command, added util for versioning enabled --- djangocms_snippet/management/__init__.py | 0 .../management/cms4_data_migration.py | 57 +++++++++++++++++++ djangocms_snippet/utils.py | 10 ++++ 3 files changed, 67 insertions(+) create mode 100644 djangocms_snippet/management/__init__.py create mode 100644 djangocms_snippet/management/cms4_data_migration.py create mode 100644 djangocms_snippet/utils.py diff --git a/djangocms_snippet/management/__init__.py b/djangocms_snippet/management/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/djangocms_snippet/management/cms4_data_migration.py b/djangocms_snippet/management/cms4_data_migration.py new file mode 100644 index 00000000..78c5aa3a --- /dev/null +++ b/djangocms_snippet/management/cms4_data_migration.py @@ -0,0 +1,57 @@ +import logging + +from django.core.management.base import BaseCommand, CommandError + +from django.conf import settings +from django.contrib.auth.models import User +from django.contrib.contenttypes.models import ContentType + +from djangocms_versioning.models import Version + +from djangocms_snippet.models import Snippet, SnippetGrouper + +from djangocms_versioning.constants import DRAFT + + +logger = logging.getLogger(__name__) + + +class Command(BaseCommand): + help = 'Command to migrate cms3 model structure into cms4 by creating relevant Groupers and Versions' + + def _create_version(snippet, state=DRAFT, number=1): + # Get a migration user. + migration_user = getattr(settings, "DJANGOCMS_SNIPPET_VERSIONING_MIGRATION_USER_ID", None) + # The contenttype of the content model + snippet_contenttype = ContentType.objects.get(app_label='djangocms_snippet', model='snippet') + + if not migration_user: + logger.warning( + "Setting DJANGOCMS_SNIPPET_VERSIONING_MIGRATION_USER_ID not provided, defaulting to user id: 1" + ) + migration_user = User.objects.get(id=1) + + logger.info("Creating version for new grouper: {}".format(snippet.pk)) + + # Create a new version for the snippet + Version.objects.create( + created_by=migration_user, + state=state, + number=number, + object_id=snippet.pk, + content_type=snippet_contenttype, + ) + + def handle(self, *args, **options): + # The queryset of populate models. + queryset = Snippet.objects.all() + + # Iterate over the queryset, create a grouper for each instance + # and map the content objects foreign key field to it. + for snippet in queryset: + if not snippet.snippet_grouper: + grouper = SnippetGrouper.objects.create() + snippet.snippet_grouper = grouper + snippet.save() + if not snippet.versions.all(): + self._create_version(snippet) diff --git a/djangocms_snippet/utils.py b/djangocms_snippet/utils.py new file mode 100644 index 00000000..91f48a2f --- /dev/null +++ b/djangocms_snippet/utils.py @@ -0,0 +1,10 @@ +from django.apps import apps + + +def is_versioning_enabled(): + from .models import Snippet + try: + app_config = apps.get_app_config('djangocms_versioning') + return app_config.cms_extension.is_content_model_versioned(Snippet) + except LookupError: + return False From dceee9fffa66ce3cb6f481e51b42d288737a78ac Mon Sep 17 00:00:00 2001 From: Adam Murray Date: Mon, 16 Aug 2021 12:41:12 +0100 Subject: [PATCH 009/107] Added tests for config as well as util for versioning check --- djangocms_snippet/cms_config.py | 24 ++++++++++++++---------- djangocms_snippet/utils.py | 10 ++++++++++ tests/test_configuration.py | 22 ++++++++++++++++++++++ 3 files changed, 46 insertions(+), 10 deletions(-) create mode 100644 djangocms_snippet/utils.py create mode 100644 tests/test_configuration.py diff --git a/djangocms_snippet/cms_config.py b/djangocms_snippet/cms_config.py index a233b105..9c4ed1b3 100644 --- a/djangocms_snippet/cms_config.py +++ b/djangocms_snippet/cms_config.py @@ -1,17 +1,21 @@ -from cms.app_base import CMSAppConfig, CMSAppExtension +from cms.app_base import CMSAppConfig -from djangocms_versioning.datastructures import VersionableItem, default_copy +from django.conf import settings from .models import Snippet class SnippetCMSAppConfig(CMSAppConfig): - djangocms_versioning_enabled = True + djangocms_versioning_enabled = getattr( + settings, 'DJANGOCMS_SNIPPET_VERSIONING_ENABLED', True) - versioning = [ - VersionableItem( - content_model=Snippet, - grouper_field_name="snippet_grouper", - copy_function=default_copy, - ) - ] + if djangocms_versioning_enabled: + from djangocms_versioning.datastructures import VersionableItem, default_copy + + versioning = [ + VersionableItem( + content_model=Snippet, + grouper_field_name="snippet_grouper", + copy_function=default_copy, + ) + ] diff --git a/djangocms_snippet/utils.py b/djangocms_snippet/utils.py new file mode 100644 index 00000000..91f48a2f --- /dev/null +++ b/djangocms_snippet/utils.py @@ -0,0 +1,10 @@ +from django.apps import apps + + +def is_versioning_enabled(): + from .models import Snippet + try: + app_config = apps.get_app_config('djangocms_versioning') + return app_config.cms_extension.is_content_model_versioned(Snippet) + except LookupError: + return False diff --git a/tests/test_configuration.py b/tests/test_configuration.py new file mode 100644 index 00000000..0c262c22 --- /dev/null +++ b/tests/test_configuration.py @@ -0,0 +1,22 @@ +from django.conf import settings +from django.test import TestCase, override_settings + +from djangocms_snippet.utils import is_versioning_enabled + + +class VersioningConfigurationTestCase(TestCase): + + @override_settings(DJANGOCMS_SNIPPET_VERSIONING_ENABLED=True) + def test_versioning_enabled_with_setting_config(self): + # Check getattr returns correct value + self.assertTrue(getattr(settings, 'DJANGOCMS_SNIPPET_VERSIONING_ENABLED')) + + # Check util is working + self.assertTrue(is_versioning_enabled()) + + def test_versioning_disabled_without_setting_config(self): + # Check getattr returns None if setting is not configured + self.assertIsNone(getattr(settings, 'DJANGOCMS_SNIPPET_VERSIONING_ENABLED', None)) + + # Util should return false + self.assertFalse(is_versioning_enabled()) From 56adbdb6352f520feb404219c3714aa02a20a351 Mon Sep 17 00:00:00 2001 From: Adam Murray Date: Mon, 16 Aug 2021 13:31:12 +0100 Subject: [PATCH 010/107] Updated cms_config --- djangocms_snippet/cms_config.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/djangocms_snippet/cms_config.py b/djangocms_snippet/cms_config.py index 9c4ed1b3..5264c557 100644 --- a/djangocms_snippet/cms_config.py +++ b/djangocms_snippet/cms_config.py @@ -7,7 +7,8 @@ class SnippetCMSAppConfig(CMSAppConfig): djangocms_versioning_enabled = getattr( - settings, 'DJANGOCMS_SNIPPET_VERSIONING_ENABLED', True) + settings, 'DJANGOCMS_SNIPPET_VERSIONING_ENABLED', False + ) if djangocms_versioning_enabled: from djangocms_versioning.datastructures import VersionableItem, default_copy From 48e125fa9f2bbbb8a5e46e386796042ef4df504f Mon Sep 17 00:00:00 2001 From: Adam Murray Date: Mon, 16 Aug 2021 15:08:16 +0100 Subject: [PATCH 011/107] Updated management command --- .../management/cms4_data_migration.py | 38 ++++++++++--------- 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/djangocms_snippet/management/cms4_data_migration.py b/djangocms_snippet/management/cms4_data_migration.py index 78c5aa3a..3892c167 100644 --- a/djangocms_snippet/management/cms4_data_migration.py +++ b/djangocms_snippet/management/cms4_data_migration.py @@ -1,10 +1,10 @@ import logging -from django.core.management.base import BaseCommand, CommandError - from django.conf import settings from django.contrib.auth.models import User from django.contrib.contenttypes.models import ContentType +from django.core.management.base import BaseCommand +from django.db import transaction from djangocms_versioning.models import Version @@ -19,12 +19,9 @@ class Command(BaseCommand): help = 'Command to migrate cms3 model structure into cms4 by creating relevant Groupers and Versions' - def _create_version(snippet, state=DRAFT, number=1): + def _create_version(self, snippet, content_type, state=DRAFT, number=1): # Get a migration user. migration_user = getattr(settings, "DJANGOCMS_SNIPPET_VERSIONING_MIGRATION_USER_ID", None) - # The contenttype of the content model - snippet_contenttype = ContentType.objects.get(app_label='djangocms_snippet', model='snippet') - if not migration_user: logger.warning( "Setting DJANGOCMS_SNIPPET_VERSIONING_MIGRATION_USER_ID not provided, defaulting to user id: 1" @@ -39,19 +36,24 @@ def _create_version(snippet, state=DRAFT, number=1): state=state, number=number, object_id=snippet.pk, - content_type=snippet_contenttype, + content_type=content_type, ) def handle(self, *args, **options): # The queryset of populate models. - queryset = Snippet.objects.all() - - # Iterate over the queryset, create a grouper for each instance - # and map the content objects foreign key field to it. - for snippet in queryset: - if not snippet.snippet_grouper: - grouper = SnippetGrouper.objects.create() - snippet.snippet_grouper = grouper - snippet.save() - if not snippet.versions.all(): - self._create_version(snippet) + queryset = Snippet._base_manager.all() + # The contenttype of the content model + snippet_contenttype = ContentType.objects.get(app_label='djangocms_snippet', model='snippet') + + # Since we are doing a database migration, use an atomic transaction + with transaction.atomic(): + # Iterate over the queryset, create a grouper for each instance which doesn't have one + # and map the content objects foreign key field to it. + for snippet in queryset: + if not snippet.snippet_grouper: + grouper = SnippetGrouper.objects.create() + snippet.snippet_grouper = grouper + snippet.save() + # If there are no versions of this content, create one. + if not snippet.versions.all(): + self._create_version(snippet, content_type=snippet_contenttype) From 5e12a63addff72d78f2b601608abf71a41fbc0ff Mon Sep 17 00:00:00 2001 From: Adam Murray Date: Mon, 16 Aug 2021 15:57:45 +0100 Subject: [PATCH 012/107] Added form, updated model and forms to improve versioned and unversioned compatibility. --- djangocms_snippet/admin.py | 2 + djangocms_snippet/forms.py | 16 +++++ ...811_0942.py => 0009_auto_20210816_0944.py} | 4 +- .../0010_migration_assign_grouper_field.py | 61 ------------------- djangocms_snippet/models.py | 1 + 5 files changed, 21 insertions(+), 63 deletions(-) create mode 100644 djangocms_snippet/forms.py rename djangocms_snippet/migrations/{0009_auto_20210811_0942.py => 0009_auto_20210816_0944.py} (74%) delete mode 100644 djangocms_snippet/migrations/0010_migration_assign_grouper_field.py diff --git a/djangocms_snippet/admin.py b/djangocms_snippet/admin.py index 9187fadd..388f88ab 100644 --- a/djangocms_snippet/admin.py +++ b/djangocms_snippet/admin.py @@ -3,10 +3,12 @@ from django.db import models from django.forms import Textarea +from .forms import SnippetForm from .models import Snippet class SnippetAdmin(admin.ModelAdmin): + form = SnippetForm list_display = ('slug', 'name') search_fields = ['slug', 'name'] prepopulated_fields = {'slug': ('name',)} diff --git a/djangocms_snippet/forms.py b/djangocms_snippet/forms.py new file mode 100644 index 00000000..a5ff0104 --- /dev/null +++ b/djangocms_snippet/forms.py @@ -0,0 +1,16 @@ +from django import forms + +from djangocms_snippet.models import Snippet, SnippetGrouper +from djangocms_snippet.utils import is_versioning_enabled + + +class SnippetForm(forms.ModelForm): + class Meta: + fields = ["name", "html", "template", "slug"] + model = Snippet + + def clean(self): + cleaned_data = super().clean() + if is_versioning_enabled and not cleaned_data.get("snippet_grouper"): + cleaned_data["snippet_grouper"] = SnippetGrouper.objects.create() + return cleaned_data diff --git a/djangocms_snippet/migrations/0009_auto_20210811_0942.py b/djangocms_snippet/migrations/0009_auto_20210816_0944.py similarity index 74% rename from djangocms_snippet/migrations/0009_auto_20210811_0942.py rename to djangocms_snippet/migrations/0009_auto_20210816_0944.py index 4f7e5cb8..086981bc 100644 --- a/djangocms_snippet/migrations/0009_auto_20210811_0942.py +++ b/djangocms_snippet/migrations/0009_auto_20210816_0944.py @@ -1,4 +1,4 @@ -# Generated by Django 2.2.24 on 2021-08-11 09:42 +# Generated by Django 2.2.24 on 2021-08-16 09:44 from django.db import migrations, models import django.db.models.deletion @@ -20,6 +20,6 @@ class Migration(migrations.Migration): migrations.AddField( model_name='snippet', name='snippet_grouper', - field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, to='djangocms_snippet.SnippetGrouper'), + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='djangocms_snippet.SnippetGrouper'), ), ] diff --git a/djangocms_snippet/migrations/0010_migration_assign_grouper_field.py b/djangocms_snippet/migrations/0010_migration_assign_grouper_field.py deleted file mode 100644 index c056a77c..00000000 --- a/djangocms_snippet/migrations/0010_migration_assign_grouper_field.py +++ /dev/null @@ -1,61 +0,0 @@ -import logging - -from django.conf import settings -from django.db import migrations - -from djangocms_versioning.constants import DRAFT - -logger = logging.getLogger(__name__) - - -def forwards(apps, schema_editor): - db_alias = schema_editor.connection.alias - # Get the models required for the data migration - SnippetModel = apps.get_model('djangocms_snippet', 'Snippet') - SnippetGrouperModel = apps.get_model('djangocms_snippet', 'SnippetGrouper') - Version = apps.get_model('djangocms_versioning', 'Version') - User = apps.get_model(*settings.AUTH_USER_MODEL.split('.')) - ContentType = apps.get_model('contenttypes', 'ContentType') - - # The queryset of populate models. - queryset = SnippetModel.objects.all() - # The contenttype of the content model - snippet_contenttype = ContentType.objects.get(app_label='djangocms_snippet', model='snippet') - - def _create_version(snippet, state=DRAFT, number=1): - # Get a migration user. - migration_user = getattr(settings, "DJANGOCMS_SNIPPET_VERSIONING_MIGRATION_USER_ID", None) - if not migration_user: - logger.warning( - "Setting DJANGOCMS_SNIPPET_VERSIONING_MIGRATION_USER_ID not provided, defaulting to user id: 1" - ) - migration_user = User.objects.get(id=1) - - logger.info("Creating version for new grouper: {}".format(snippet.pk)) - - # Create a new version for the snippet - Version.objects.using(db_alias).create( - created_by=migration_user, - state=state, - number=number, - object_id=snippet.pk, - content_type=snippet_contenttype, - ) - - # Iterate over the queryset, create a grouper for each instance and map the content objects foreign key field to it. - for snippet in queryset: - grouper = SnippetGrouperModel.objects.create() - snippet.snippet_grouper = grouper - snippet.save() - _create_version(snippet) - - -class Migration(migrations.Migration): - - dependencies = [ - ('djangocms_snippet', '0009_auto_20210811_0942'), - ] - - operations = [ - migrations.RunPython(forwards) - ] diff --git a/djangocms_snippet/models.py b/djangocms_snippet/models.py index e1c65280..99269503 100644 --- a/djangocms_snippet/models.py +++ b/djangocms_snippet/models.py @@ -27,6 +27,7 @@ class Snippet(models.Model): SnippetGrouper, on_delete=models.PROTECT, null=True, + blank=True, ) html = models.TextField( verbose_name=_('HTML'), From fdcde12c59bfddff8a4881e52ef7dcd56c24a906 Mon Sep 17 00:00:00 2001 From: Adam Murray Date: Tue, 31 Aug 2021 16:03:18 +0100 Subject: [PATCH 013/107] Updated migration, removed unecessary plugin --- djangocms_snippet/admin.py | 4 + djangocms_snippet/forms.py | 17 +++ djangocms_snippet/management/__init__.py | 0 .../management/commands/__init__.py | 0 .../commands/cms4_data_migration.py | 102 ++++++++++++++++++ .../migrations/0009_auto_20210831_0715.py | 40 +++++++ .../0010_remove_snippetptr_snippet.py | 17 +++ .../migrations/0011_auto_20210831_0801.py | 18 ++++ djangocms_snippet/utils.py | 10 ++ 9 files changed, 208 insertions(+) create mode 100644 djangocms_snippet/forms.py create mode 100644 djangocms_snippet/management/__init__.py create mode 100644 djangocms_snippet/management/commands/__init__.py create mode 100644 djangocms_snippet/management/commands/cms4_data_migration.py create mode 100644 djangocms_snippet/migrations/0009_auto_20210831_0715.py create mode 100644 djangocms_snippet/migrations/0010_remove_snippetptr_snippet.py create mode 100644 djangocms_snippet/migrations/0011_auto_20210831_0801.py create mode 100644 djangocms_snippet/utils.py diff --git a/djangocms_snippet/admin.py b/djangocms_snippet/admin.py index 9187fadd..0818e63e 100644 --- a/djangocms_snippet/admin.py +++ b/djangocms_snippet/admin.py @@ -3,10 +3,14 @@ from django.db import models from django.forms import Textarea +# from djangocms_versioning.admin import ExtendedVersionAdminMixin + +# from .forms import SnippetForm from .models import Snippet class SnippetAdmin(admin.ModelAdmin): + # form = SnippetForm list_display = ('slug', 'name') search_fields = ['slug', 'name'] prepopulated_fields = {'slug': ('name',)} diff --git a/djangocms_snippet/forms.py b/djangocms_snippet/forms.py new file mode 100644 index 00000000..7e479f6a --- /dev/null +++ b/djangocms_snippet/forms.py @@ -0,0 +1,17 @@ +from django import forms + +# from djangocms_snippet.models import Snippet, SnippetGrouper +from djangocms_snippet.utils import is_versioning_enabled + +""" +class SnippetForm(forms.ModelForm): + class Meta: + fields = ["name", "html", "template", "slug"] + model = Snippet + + def clean(self): + cleaned_data = super().clean() + if is_versioning_enabled and not cleaned_data.get("snippet_grouper"): + cleaned_data["snippet_grouper"] = SnippetGrouper.objects.create() + return cleaned_data +""" diff --git a/djangocms_snippet/management/__init__.py b/djangocms_snippet/management/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/djangocms_snippet/management/commands/__init__.py b/djangocms_snippet/management/commands/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/djangocms_snippet/management/commands/cms4_data_migration.py b/djangocms_snippet/management/commands/cms4_data_migration.py new file mode 100644 index 00000000..a5fb6fcf --- /dev/null +++ b/djangocms_snippet/management/commands/cms4_data_migration.py @@ -0,0 +1,102 @@ +import logging + +from django.conf import settings +from django.contrib.auth.models import User +from django.contrib.contenttypes.models import ContentType +from django.core.management.base import BaseCommand +from django.db import transaction + +from cms.api import add_plugin + +from djangocms_snippet.cms_plugins import SnippetPtrPlugin +from djangocms_snippet.models import Snippet, SnippetGrouper, SnippetPtr +from djangocms_versioning.constants import DRAFT +from djangocms_versioning.models import Version + + +logger = logging.getLogger(__name__) + + +class Command(BaseCommand): + help = 'Command to migrate cms3 model structure into cms4 by creating relevant Groupers and Versions' + + def _create_version(self, snippet, state=DRAFT, number=1): + # Get a migration user. + migration_user = getattr(settings, "DJANGOCMS_SNIPPET_VERSIONING_MIGRATION_USER_ID", None) + if not migration_user: + logger.warning( + "Setting DJANGOCMS_SNIPPET_VERSIONING_MIGRATION_USER_ID not provided, defaulting to user id: 1" + ) + migration_user = User.objects.get(id=1) + + # The contenttype of the content model + snippet_contenttype = ContentType.objects.get(app_label='djangocms_snippet', model='snippet') + + logger.info("Creating version for new grouper: {}".format(snippet.pk)) + # Create a new version for the snippet + Version.objects.create( + created_by=migration_user, + state=state, + number=number, + object_id=snippet.pk, + content_type=snippet_contenttype, + ) + + def _create_plugin(self, old_plugin, grouper): + # Create the new plugin + new_plugin = add_plugin( + old_plugin.placeholder, + plugin_type=SnippetPtrPlugin, + language="en", + snippet=old_plugin.snippet, + new_snippet=grouper, + ) + old_plugin_position = old_plugin.position + old_plugin_id = old_plugin.id + + if new_plugin: + logger.info(f"Deleting CMS3 Plugin: {old_plugin_id}") + old_plugin.cmsplugin_ptr_id = old_plugin.cmsplugin_ptr + old_plugin.delete() + + new_plugin.position = old_plugin_position + logger.info( + f"Created CMS4 Snippet plugin: {type(new_plugin)}-{new_plugin.id}, for CMS3 plugin: {old_plugin_id}" + ) + + def handle(self, *args, **options): + # The queryset of populated models. + queryset = Snippet._base_manager.all() + # The plugin queryset + plugin_queryset = SnippetPtr.objects.all() + + # Since we are doing a database migration, use an atomic transaction + with transaction.atomic(): + version_count = 0 + grouper_count = 0 + plugin_count = 0 + # Iterate over the queryset, create a grouper for each instance which doesn't have one + # and map the content objects foreign key field to it. + for snippet in queryset: + if not snippet.snippet_grouper: + grouper = SnippetGrouper.objects.create() + snippet.snippet_grouper = grouper + snippet.save() + logger.info("Created Snippet Grouper") + grouper_count += 1 + # If there are no versions of this content, create one. + if hasattr(snippet, "versions"): + if not snippet.versions.all(): + self._create_version(snippet=snippet) + version_count += 1 + + # Iterate over the plugin queryset, and create a new CMS4 plugin for every CMS3 plugin, + # then delete the old CMS3 plugin + for plugin in plugin_queryset: + self._create_plugin(plugin, snippet.snippet_grouper) + plugin_count += 1 + + logger.info( + f'''Created {version_count} version objects, {grouper_count}''' + + f'''Snippet grouper objects and {plugin_count} snippet plugins''' + ) diff --git a/djangocms_snippet/migrations/0009_auto_20210831_0715.py b/djangocms_snippet/migrations/0009_auto_20210831_0715.py new file mode 100644 index 00000000..09a033b5 --- /dev/null +++ b/djangocms_snippet/migrations/0009_auto_20210831_0715.py @@ -0,0 +1,40 @@ +# Generated by Django 2.2.24 on 2021-08-31 07:15 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('djangocms_snippet', '0008_auto_change_name'), + ] + + operations = [ + migrations.CreateModel( + name='SnippetGrouper', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ], + ), + migrations.AlterField( + model_name='snippet', + name='name', + field=models.CharField(max_length=255, verbose_name='Name'), + ), + migrations.AlterField( + model_name='snippet', + name='slug', + field=models.SlugField(default='', max_length=255, verbose_name='Slug'), + ), + migrations.AddField( + model_name='snippet', + name='snippet_grouper', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='djangocms_snippet.SnippetGrouper'), + ), + migrations.AddField( + model_name='snippetptr', + name='new_snippet', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='djangocms_snippet.SnippetGrouper'), + ), + ] diff --git a/djangocms_snippet/migrations/0010_remove_snippetptr_snippet.py b/djangocms_snippet/migrations/0010_remove_snippetptr_snippet.py new file mode 100644 index 00000000..5cc6abd5 --- /dev/null +++ b/djangocms_snippet/migrations/0010_remove_snippetptr_snippet.py @@ -0,0 +1,17 @@ +# Generated by Django 2.2.24 on 2021-08-31 08:00 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('djangocms_snippet', '0009_auto_20210831_0715'), + ] + + operations = [ + migrations.RemoveField( + model_name='snippetptr', + name='snippet', + ), + ] diff --git a/djangocms_snippet/migrations/0011_auto_20210831_0801.py b/djangocms_snippet/migrations/0011_auto_20210831_0801.py new file mode 100644 index 00000000..0acc7708 --- /dev/null +++ b/djangocms_snippet/migrations/0011_auto_20210831_0801.py @@ -0,0 +1,18 @@ +# Generated by Django 2.2.24 on 2021-08-31 08:01 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('djangocms_snippet', '0010_remove_snippetptr_snippet'), + ] + + operations = [ + migrations.RenameField( + model_name='snippetptr', + old_name='new_snippet', + new_name='snippet', + ), + ] diff --git a/djangocms_snippet/utils.py b/djangocms_snippet/utils.py new file mode 100644 index 00000000..91f48a2f --- /dev/null +++ b/djangocms_snippet/utils.py @@ -0,0 +1,10 @@ +from django.apps import apps + + +def is_versioning_enabled(): + from .models import Snippet + try: + app_config = apps.get_app_config('djangocms_versioning') + return app_config.cms_extension.is_content_model_versioned(Snippet) + except LookupError: + return False From 9b73d5957da531cd4e1f1575f1e7246ad1cfb719 Mon Sep 17 00:00:00 2001 From: Adam Murray Date: Tue, 31 Aug 2021 16:38:52 +0100 Subject: [PATCH 014/107] Removed additional copies of files --- .../management/cms4_data_migration.py | 59 ------------------- .../migrations/0009_auto_20210816_0944.py | 25 -------- 2 files changed, 84 deletions(-) delete mode 100644 djangocms_snippet/management/cms4_data_migration.py delete mode 100644 djangocms_snippet/migrations/0009_auto_20210816_0944.py diff --git a/djangocms_snippet/management/cms4_data_migration.py b/djangocms_snippet/management/cms4_data_migration.py deleted file mode 100644 index 3892c167..00000000 --- a/djangocms_snippet/management/cms4_data_migration.py +++ /dev/null @@ -1,59 +0,0 @@ -import logging - -from django.conf import settings -from django.contrib.auth.models import User -from django.contrib.contenttypes.models import ContentType -from django.core.management.base import BaseCommand -from django.db import transaction - -from djangocms_versioning.models import Version - -from djangocms_snippet.models import Snippet, SnippetGrouper - -from djangocms_versioning.constants import DRAFT - - -logger = logging.getLogger(__name__) - - -class Command(BaseCommand): - help = 'Command to migrate cms3 model structure into cms4 by creating relevant Groupers and Versions' - - def _create_version(self, snippet, content_type, state=DRAFT, number=1): - # Get a migration user. - migration_user = getattr(settings, "DJANGOCMS_SNIPPET_VERSIONING_MIGRATION_USER_ID", None) - if not migration_user: - logger.warning( - "Setting DJANGOCMS_SNIPPET_VERSIONING_MIGRATION_USER_ID not provided, defaulting to user id: 1" - ) - migration_user = User.objects.get(id=1) - - logger.info("Creating version for new grouper: {}".format(snippet.pk)) - - # Create a new version for the snippet - Version.objects.create( - created_by=migration_user, - state=state, - number=number, - object_id=snippet.pk, - content_type=content_type, - ) - - def handle(self, *args, **options): - # The queryset of populate models. - queryset = Snippet._base_manager.all() - # The contenttype of the content model - snippet_contenttype = ContentType.objects.get(app_label='djangocms_snippet', model='snippet') - - # Since we are doing a database migration, use an atomic transaction - with transaction.atomic(): - # Iterate over the queryset, create a grouper for each instance which doesn't have one - # and map the content objects foreign key field to it. - for snippet in queryset: - if not snippet.snippet_grouper: - grouper = SnippetGrouper.objects.create() - snippet.snippet_grouper = grouper - snippet.save() - # If there are no versions of this content, create one. - if not snippet.versions.all(): - self._create_version(snippet, content_type=snippet_contenttype) diff --git a/djangocms_snippet/migrations/0009_auto_20210816_0944.py b/djangocms_snippet/migrations/0009_auto_20210816_0944.py deleted file mode 100644 index 086981bc..00000000 --- a/djangocms_snippet/migrations/0009_auto_20210816_0944.py +++ /dev/null @@ -1,25 +0,0 @@ -# Generated by Django 2.2.24 on 2021-08-16 09:44 - -from django.db import migrations, models -import django.db.models.deletion - - -class Migration(migrations.Migration): - - dependencies = [ - ('djangocms_snippet', '0008_auto_change_name'), - ] - - operations = [ - migrations.CreateModel( - name='SnippetGrouper', - fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ], - ), - migrations.AddField( - model_name='snippet', - name='snippet_grouper', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='djangocms_snippet.SnippetGrouper'), - ), - ] From 680ce707f6e7600f1ea3e3932040cc21f61bf26b Mon Sep 17 00:00:00 2001 From: Adam Murray Date: Wed, 1 Sep 2021 16:25:59 +0100 Subject: [PATCH 015/107] Split migration command into migration and command --- .../commands/cms4_data_migration.py | 51 +------------ .../migrations/0010_cms4_migration.py | 73 +++++++++++++++++++ .../0010_remove_snippetptr_snippet.py | 17 ----- .../migrations/0011_auto_20210831_0801.py | 18 ----- 4 files changed, 77 insertions(+), 82 deletions(-) create mode 100644 djangocms_snippet/migrations/0010_cms4_migration.py delete mode 100644 djangocms_snippet/migrations/0010_remove_snippetptr_snippet.py delete mode 100644 djangocms_snippet/migrations/0011_auto_20210831_0801.py diff --git a/djangocms_snippet/management/commands/cms4_data_migration.py b/djangocms_snippet/management/commands/cms4_data_migration.py index a5fb6fcf..4de8a851 100644 --- a/djangocms_snippet/management/commands/cms4_data_migration.py +++ b/djangocms_snippet/management/commands/cms4_data_migration.py @@ -6,10 +6,7 @@ from django.core.management.base import BaseCommand from django.db import transaction -from cms.api import add_plugin - -from djangocms_snippet.cms_plugins import SnippetPtrPlugin -from djangocms_snippet.models import Snippet, SnippetGrouper, SnippetPtr +from djangocms_snippet.models import Snippet from djangocms_versioning.constants import DRAFT from djangocms_versioning.models import Version @@ -42,61 +39,21 @@ def _create_version(self, snippet, state=DRAFT, number=1): content_type=snippet_contenttype, ) - def _create_plugin(self, old_plugin, grouper): - # Create the new plugin - new_plugin = add_plugin( - old_plugin.placeholder, - plugin_type=SnippetPtrPlugin, - language="en", - snippet=old_plugin.snippet, - new_snippet=grouper, - ) - old_plugin_position = old_plugin.position - old_plugin_id = old_plugin.id - - if new_plugin: - logger.info(f"Deleting CMS3 Plugin: {old_plugin_id}") - old_plugin.cmsplugin_ptr_id = old_plugin.cmsplugin_ptr - old_plugin.delete() - - new_plugin.position = old_plugin_position - logger.info( - f"Created CMS4 Snippet plugin: {type(new_plugin)}-{new_plugin.id}, for CMS3 plugin: {old_plugin_id}" - ) - def handle(self, *args, **options): # The queryset of populated models. queryset = Snippet._base_manager.all() - # The plugin queryset - plugin_queryset = SnippetPtr.objects.all() # Since we are doing a database migration, use an atomic transaction with transaction.atomic(): version_count = 0 - grouper_count = 0 - plugin_count = 0 - # Iterate over the queryset, create a grouper for each instance which doesn't have one - # and map the content objects foreign key field to it. + for snippet in queryset: - if not snippet.snippet_grouper: - grouper = SnippetGrouper.objects.create() - snippet.snippet_grouper = grouper - snippet.save() - logger.info("Created Snippet Grouper") - grouper_count += 1 - # If there are no versions of this content, create one. + # If there are no versions of this content, create one. if hasattr(snippet, "versions"): if not snippet.versions.all(): self._create_version(snippet=snippet) version_count += 1 - # Iterate over the plugin queryset, and create a new CMS4 plugin for every CMS3 plugin, - # then delete the old CMS3 plugin - for plugin in plugin_queryset: - self._create_plugin(plugin, snippet.snippet_grouper) - plugin_count += 1 - logger.info( - f'''Created {version_count} version objects, {grouper_count}''' + - f'''Snippet grouper objects and {plugin_count} snippet plugins''' + f"Created {version_count} version objects" ) diff --git a/djangocms_snippet/migrations/0010_cms4_migration.py b/djangocms_snippet/migrations/0010_cms4_migration.py new file mode 100644 index 00000000..d09912cf --- /dev/null +++ b/djangocms_snippet/migrations/0010_cms4_migration.py @@ -0,0 +1,73 @@ +# Generated by Django 2.2.24 on 2021-08-31 10:45 +import logging +from django.db import migrations + +from cms.api import add_plugin + +from djangocms_snippet.cms_plugins import SnippetPtrPlugin + +logger = logging.getLogger(__name__) + + +def _create_plugin(old_plugin, grouper): + # Create the new plugin + new_plugin = add_plugin( + old_plugin.placeholder, + plugin_type=SnippetPtrPlugin, + language="en", + snippet=old_plugin.snippet, + new_snippet=grouper, + ) + old_plugin_position = old_plugin.position + old_plugin_id = old_plugin.id + + if new_plugin: + logger.info(f"Deleting CMS3 Plugin: {old_plugin_id}") + old_plugin.cmsplugin_ptr_id = old_plugin.cmsplugin_ptr + old_plugin.delete() + + new_plugin.position = old_plugin_position + logger.info( + f"Created CMS4 Snippet plugin: {type(new_plugin)}-{new_plugin.id}, for CMS3 plugin: {old_plugin_id}" + ) + + +def create_groupers(snippet, grouper_model): + grouper = grouper_model.model.objects.create() + snippet.snippet_grouper = grouper + snippet.save() + logger.info("Created Snippet Grouper") + + +def cms4_migration(apps, schema_editor): + grouper_count = 0 + plugin_count = 0 + Snippet = apps.get_model("djangocms_snippet", "Snippet") + SnippetGrouper = apps.get_model("djangocms_snippet", "SnippetGrouper") + SnippetPtr = apps.get_model("djangocms_snippet", "SnippetPtr") + + # Iterate over the queryset, create a grouper for each instance which doesn't have one + # and map the content objects foreign key field to it. + for snippet in Snippet.objects.all(): + if not snippet.snippet_grouper: + create_groupers(snippet, SnippetGrouper) + grouper_count += 1 + + logger.info(f"SnippetPlugin count pre-migration: {SnippetPtr.objects.all().count()}") + # Iterate over the plugin queryset, and replace them each with a CMS4 plugin + for snippet in SnippetPtr.objects.all(): + _create_plugin(snippet, snippet.snippet_grouper) + plugin_count += 1 + + logger.info(f"Migration completed, created {grouper_count} Snippet Groupers and {plugin_count} Snippet plugins") + + +class Migration(migrations.Migration): + + dependencies = [ + ('djangocms_snippet', '0009_auto_20210831_0715'), + ] + + operations = [ + migrations.RunPython(cms4_migration) + ] diff --git a/djangocms_snippet/migrations/0010_remove_snippetptr_snippet.py b/djangocms_snippet/migrations/0010_remove_snippetptr_snippet.py deleted file mode 100644 index 5cc6abd5..00000000 --- a/djangocms_snippet/migrations/0010_remove_snippetptr_snippet.py +++ /dev/null @@ -1,17 +0,0 @@ -# Generated by Django 2.2.24 on 2021-08-31 08:00 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('djangocms_snippet', '0009_auto_20210831_0715'), - ] - - operations = [ - migrations.RemoveField( - model_name='snippetptr', - name='snippet', - ), - ] diff --git a/djangocms_snippet/migrations/0011_auto_20210831_0801.py b/djangocms_snippet/migrations/0011_auto_20210831_0801.py deleted file mode 100644 index 0acc7708..00000000 --- a/djangocms_snippet/migrations/0011_auto_20210831_0801.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 2.2.24 on 2021-08-31 08:01 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('djangocms_snippet', '0010_remove_snippetptr_snippet'), - ] - - operations = [ - migrations.RenameField( - model_name='snippetptr', - old_name='new_snippet', - new_name='snippet', - ), - ] From 8dc7f91d370cf27dbaa9259fde984a09f0e12d70 Mon Sep 17 00:00:00 2001 From: Adam Murray Date: Thu, 2 Sep 2021 15:25:21 +0100 Subject: [PATCH 016/107] Updates to migration --- djangocms_snippet/management/commands/cms4_data_migration.py | 2 +- djangocms_snippet/models.py | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/djangocms_snippet/management/commands/cms4_data_migration.py b/djangocms_snippet/management/commands/cms4_data_migration.py index 4de8a851..f137c3cd 100644 --- a/djangocms_snippet/management/commands/cms4_data_migration.py +++ b/djangocms_snippet/management/commands/cms4_data_migration.py @@ -6,7 +6,7 @@ from django.core.management.base import BaseCommand from django.db import transaction -from djangocms_snippet.models import Snippet +from djangocms_snippet.models import Snippet, SnippetGrouper, SnippetPtr from djangocms_versioning.constants import DRAFT from djangocms_versioning.models import Version diff --git a/djangocms_snippet/models.py b/djangocms_snippet/models.py index 99269503..42fac2f9 100644 --- a/djangocms_snippet/models.py +++ b/djangocms_snippet/models.py @@ -73,7 +73,8 @@ class SnippetPtr(CMSPlugin): on_delete=models.CASCADE, ) - snippet = models.ForeignKey(Snippet, on_delete=models.CASCADE,) + snippet = models.ForeignKey(Snippet, on_delete=models.CASCADE) + new_snippet = models.ForeignKey(SnippetGrouper, on_delete=models.CASCADE) search_fields = ['snippet__html'] if SEARCH_ENABLED else [] From 6e937e8cb0469813dd0d62a0b86b66a580a760ef Mon Sep 17 00:00:00 2001 From: Adam Murray Date: Thu, 2 Sep 2021 15:25:58 +0100 Subject: [PATCH 017/107] Updates to migration --- .../migrations/0010_cms4_migration.py | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/djangocms_snippet/migrations/0010_cms4_migration.py b/djangocms_snippet/migrations/0010_cms4_migration.py index d09912cf..27a1b109 100644 --- a/djangocms_snippet/migrations/0010_cms4_migration.py +++ b/djangocms_snippet/migrations/0010_cms4_migration.py @@ -4,7 +4,7 @@ from cms.api import add_plugin -from djangocms_snippet.cms_plugins import SnippetPtrPlugin +from djangocms_snippet.cms_plugins import SnippetPlugin logger = logging.getLogger(__name__) @@ -12,11 +12,10 @@ def _create_plugin(old_plugin, grouper): # Create the new plugin new_plugin = add_plugin( - old_plugin.placeholder, - plugin_type=SnippetPtrPlugin, + placeholder=old_plugin.placeholder, + plugin_type=SnippetPlugin, language="en", - snippet=old_plugin.snippet, - new_snippet=grouper, + snippet=grouper, ) old_plugin_position = old_plugin.position old_plugin_id = old_plugin.id @@ -33,7 +32,7 @@ def _create_plugin(old_plugin, grouper): def create_groupers(snippet, grouper_model): - grouper = grouper_model.model.objects.create() + grouper = grouper_model.objects.create() snippet.snippet_grouper = grouper snippet.save() logger.info("Created Snippet Grouper") @@ -55,8 +54,8 @@ def cms4_migration(apps, schema_editor): logger.info(f"SnippetPlugin count pre-migration: {SnippetPtr.objects.all().count()}") # Iterate over the plugin queryset, and replace them each with a CMS4 plugin - for snippet in SnippetPtr.objects.all(): - _create_plugin(snippet, snippet.snippet_grouper) + for snippet_plugin in SnippetPtr.objects.all(): + _create_plugin(snippet_plugin, snippet_plugin.snippet) plugin_count += 1 logger.info(f"Migration completed, created {grouper_count} Snippet Groupers and {plugin_count} Snippet plugins") From 2df658bdb22486c478761e8d68a83e932b1d082e Mon Sep 17 00:00:00 2001 From: Adam Murray Date: Fri, 3 Sep 2021 11:25:50 +0100 Subject: [PATCH 018/107] Update migration for review --- .../migrations/0010_cms4_migration.py | 42 +++++++++++++++---- 1 file changed, 33 insertions(+), 9 deletions(-) diff --git a/djangocms_snippet/migrations/0010_cms4_migration.py b/djangocms_snippet/migrations/0010_cms4_migration.py index 27a1b109..7fc70bac 100644 --- a/djangocms_snippet/migrations/0010_cms4_migration.py +++ b/djangocms_snippet/migrations/0010_cms4_migration.py @@ -1,33 +1,55 @@ # Generated by Django 2.2.24 on 2021-08-31 10:45 import logging +from django.apps import apps from django.db import migrations -from cms.api import add_plugin +from cms.plugin_pool import plugin_pool from djangocms_snippet.cms_plugins import SnippetPlugin logger = logging.getLogger(__name__) -def _create_plugin(old_plugin, grouper): +def _create_plugin(old_plugin, grouper, Plugin): # Create the new plugin - new_plugin = add_plugin( - placeholder=old_plugin.placeholder, + parent_id = None + if old_plugin.parent: + parent_id = old_plugin.parent + + plugin_base = Plugin( plugin_type=SnippetPlugin, + placeholder=old_plugin.placeholder, + position=1, language="en", - snippet=grouper, + parent_id=parent_id, ) + + try: + plugin_model = plugin_pool.get_plugin("SnippetPlugin").model + except KeyError: + raise TypeError( + 'plugin_type must be CMSPluginBase subclass or string' + ) + + import pdb + pdb.set_trace() + plugin_base = old_plugin.placeholder.add_plugin(plugin_base) + old_plugin_position = old_plugin.position old_plugin_id = old_plugin.id - if new_plugin: + plugin_base.position = old_plugin_position + plugin = plugin_model({"snippet": old_plugin.snippet, "new_snippet": grouper}) + plugin_base.set_base_attr(plugin) + + if plugin_base: logger.info(f"Deleting CMS3 Plugin: {old_plugin_id}") old_plugin.cmsplugin_ptr_id = old_plugin.cmsplugin_ptr old_plugin.delete() + plugin_base.save() - new_plugin.position = old_plugin_position logger.info( - f"Created CMS4 Snippet plugin: {type(new_plugin)}-{new_plugin.id}, for CMS3 plugin: {old_plugin_id}" + f"Created CMS4 Snippet plugin: {type(plugin)}-{plugin.id}, for CMS3 plugin: {old_plugin_id}" ) @@ -44,6 +66,8 @@ def cms4_migration(apps, schema_editor): Snippet = apps.get_model("djangocms_snippet", "Snippet") SnippetGrouper = apps.get_model("djangocms_snippet", "SnippetGrouper") SnippetPtr = apps.get_model("djangocms_snippet", "SnippetPtr") + Plugin = apps.get_model('cms', 'CMSPlugin') + Placeholder = apps.get_model('cms', 'Placeholder') # Iterate over the queryset, create a grouper for each instance which doesn't have one # and map the content objects foreign key field to it. @@ -55,7 +79,7 @@ def cms4_migration(apps, schema_editor): logger.info(f"SnippetPlugin count pre-migration: {SnippetPtr.objects.all().count()}") # Iterate over the plugin queryset, and replace them each with a CMS4 plugin for snippet_plugin in SnippetPtr.objects.all(): - _create_plugin(snippet_plugin, snippet_plugin.snippet) + _create_plugin(snippet_plugin, snippet_plugin.snippet, SnippetPtr) plugin_count += 1 logger.info(f"Migration completed, created {grouper_count} Snippet Groupers and {plugin_count} Snippet plugins") From 11a7d3e2961bd1ec54ec477843fd963f7c562058 Mon Sep 17 00:00:00 2001 From: Adam Murray Date: Fri, 3 Sep 2021 11:26:50 +0100 Subject: [PATCH 019/107] Remove pdb --- djangocms_snippet/migrations/0010_cms4_migration.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/djangocms_snippet/migrations/0010_cms4_migration.py b/djangocms_snippet/migrations/0010_cms4_migration.py index 7fc70bac..f4f717eb 100644 --- a/djangocms_snippet/migrations/0010_cms4_migration.py +++ b/djangocms_snippet/migrations/0010_cms4_migration.py @@ -31,8 +31,6 @@ def _create_plugin(old_plugin, grouper, Plugin): 'plugin_type must be CMSPluginBase subclass or string' ) - import pdb - pdb.set_trace() plugin_base = old_plugin.placeholder.add_plugin(plugin_base) old_plugin_position = old_plugin.position From d7c5dbb47e9a995d4898b4723cdae4478c7542e3 Mon Sep 17 00:00:00 2001 From: Adam Murray Date: Fri, 3 Sep 2021 12:34:19 +0100 Subject: [PATCH 020/107] Migration upgrade --- .../migrations/0010_cms4_migration.py | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) diff --git a/djangocms_snippet/migrations/0010_cms4_migration.py b/djangocms_snippet/migrations/0010_cms4_migration.py index f4f717eb..d9bf4ef4 100644 --- a/djangocms_snippet/migrations/0010_cms4_migration.py +++ b/djangocms_snippet/migrations/0010_cms4_migration.py @@ -24,21 +24,12 @@ def _create_plugin(old_plugin, grouper, Plugin): parent_id=parent_id, ) - try: - plugin_model = plugin_pool.get_plugin("SnippetPlugin").model - except KeyError: - raise TypeError( - 'plugin_type must be CMSPluginBase subclass or string' - ) - - plugin_base = old_plugin.placeholder.add_plugin(plugin_base) - old_plugin_position = old_plugin.position old_plugin_id = old_plugin.id plugin_base.position = old_plugin_position - plugin = plugin_model({"snippet": old_plugin.snippet, "new_snippet": grouper}) - plugin_base.set_base_attr(plugin) + plugin_base.snippet = old_plugin.snippet + plugin_base.new_snippet = grouper if plugin_base: logger.info(f"Deleting CMS3 Plugin: {old_plugin_id}") @@ -47,7 +38,7 @@ def _create_plugin(old_plugin, grouper, Plugin): plugin_base.save() logger.info( - f"Created CMS4 Snippet plugin: {type(plugin)}-{plugin.id}, for CMS3 plugin: {old_plugin_id}" + f"Created CMS4 Snippet plugin: {type(plugin_base)}-{plugin_base.id}, for CMS3 plugin: {old_plugin_id}" ) @@ -64,8 +55,6 @@ def cms4_migration(apps, schema_editor): Snippet = apps.get_model("djangocms_snippet", "Snippet") SnippetGrouper = apps.get_model("djangocms_snippet", "SnippetGrouper") SnippetPtr = apps.get_model("djangocms_snippet", "SnippetPtr") - Plugin = apps.get_model('cms', 'CMSPlugin') - Placeholder = apps.get_model('cms', 'Placeholder') # Iterate over the queryset, create a grouper for each instance which doesn't have one # and map the content objects foreign key field to it. @@ -77,7 +66,7 @@ def cms4_migration(apps, schema_editor): logger.info(f"SnippetPlugin count pre-migration: {SnippetPtr.objects.all().count()}") # Iterate over the plugin queryset, and replace them each with a CMS4 plugin for snippet_plugin in SnippetPtr.objects.all(): - _create_plugin(snippet_plugin, snippet_plugin.snippet, SnippetPtr) + _create_plugin(snippet_plugin, snippet_plugin.new_snippet, SnippetPtr) plugin_count += 1 logger.info(f"Migration completed, created {grouper_count} Snippet Groupers and {plugin_count} Snippet plugins") From 8898232097309eac7f1396b05abd0effac2c0d6c Mon Sep 17 00:00:00 2001 From: Adam Murray Date: Fri, 3 Sep 2021 17:49:00 +0100 Subject: [PATCH 021/107] Remove plugin from migration 10, added version creation --- .../0010_cms4_grouper_version_migration.py | 63 ++++++++++++++ .../migrations/0010_cms4_migration.py | 83 ------------------- 2 files changed, 63 insertions(+), 83 deletions(-) create mode 100644 djangocms_snippet/migrations/0010_cms4_grouper_version_migration.py delete mode 100644 djangocms_snippet/migrations/0010_cms4_migration.py diff --git a/djangocms_snippet/migrations/0010_cms4_grouper_version_migration.py b/djangocms_snippet/migrations/0010_cms4_grouper_version_migration.py new file mode 100644 index 00000000..3c6a8fa7 --- /dev/null +++ b/djangocms_snippet/migrations/0010_cms4_grouper_version_migration.py @@ -0,0 +1,63 @@ +import logging +import settings + +from django.db import migrations + +# TODO: Remove this +from djangocms_versioning.constants import DRAFT + +logger = logging.getLogger(__name__) + + +def cms4_grouper_version_migration(apps, schema_editor): + grouper_count = 0 + version_count = 0 + + ContentType = apps.get_model("contenttypes", "ContentType") + Snippet = apps.get_model("djangocms_snippet", "Snippet") + SnippetGrouper = apps.get_model("djangocms_snippet", "SnippetGrouper") + User = apps.get_model('auth', 'User') + Version = apps.get_model("djangocms_versioning", "Version") + + snippet_contenttype = ContentType.objects.get(app_label='djangocms_snippet', model='snippet') + snippet_queryset = Snippet.objects.all() + + for snippet in snippet_queryset: + grouper = SnippetGrouper.objects.create() + snippet.new_snippet = grouper + snippet.save() + logger.info(f"Created Snippet Grouper ID: {snippet.snippet_grouper}") + grouper_count += 1 + + # Get a migration user. + # TODO: Use environment variable, fall back to setting, then to default + migration_user = getattr(settings, "DJANGOCMS_SNIPPET_VERSIONING_MIGRATION_USER_ID", None) + if not migration_user: + logger.warning( + "Setting DJANGOCMS_SNIPPET_VERSIONING_MIGRATION_USER_ID not provided, defaulting to user id: 1" + ) + migration_user = User.objects.get(id=1) + + version = Version.objects.create( + created_by=migration_user, + state=DRAFT, + number=1, + object_id=snippet.pk, + content_type=snippet_contenttype, + ) + logger.info(f"Created Snippet Version ID: {version.pk}") + # This will be necessary when versioning checks are implemented + version_count += 1 + + logger.info(f"Migration created {grouper_count} SnippetGrouper models and {version_count} Version models") + + +class Migration(migrations.Migration): + + dependencies = [ + ('djangocms_snippet', '0009_auto_20210831_0715'), + ] + + operations = [ + migrations.RunPython(cms4_grouper_version_migration) + ] diff --git a/djangocms_snippet/migrations/0010_cms4_migration.py b/djangocms_snippet/migrations/0010_cms4_migration.py deleted file mode 100644 index d9bf4ef4..00000000 --- a/djangocms_snippet/migrations/0010_cms4_migration.py +++ /dev/null @@ -1,83 +0,0 @@ -# Generated by Django 2.2.24 on 2021-08-31 10:45 -import logging -from django.apps import apps -from django.db import migrations - -from cms.plugin_pool import plugin_pool - -from djangocms_snippet.cms_plugins import SnippetPlugin - -logger = logging.getLogger(__name__) - - -def _create_plugin(old_plugin, grouper, Plugin): - # Create the new plugin - parent_id = None - if old_plugin.parent: - parent_id = old_plugin.parent - - plugin_base = Plugin( - plugin_type=SnippetPlugin, - placeholder=old_plugin.placeholder, - position=1, - language="en", - parent_id=parent_id, - ) - - old_plugin_position = old_plugin.position - old_plugin_id = old_plugin.id - - plugin_base.position = old_plugin_position - plugin_base.snippet = old_plugin.snippet - plugin_base.new_snippet = grouper - - if plugin_base: - logger.info(f"Deleting CMS3 Plugin: {old_plugin_id}") - old_plugin.cmsplugin_ptr_id = old_plugin.cmsplugin_ptr - old_plugin.delete() - plugin_base.save() - - logger.info( - f"Created CMS4 Snippet plugin: {type(plugin_base)}-{plugin_base.id}, for CMS3 plugin: {old_plugin_id}" - ) - - -def create_groupers(snippet, grouper_model): - grouper = grouper_model.objects.create() - snippet.snippet_grouper = grouper - snippet.save() - logger.info("Created Snippet Grouper") - - -def cms4_migration(apps, schema_editor): - grouper_count = 0 - plugin_count = 0 - Snippet = apps.get_model("djangocms_snippet", "Snippet") - SnippetGrouper = apps.get_model("djangocms_snippet", "SnippetGrouper") - SnippetPtr = apps.get_model("djangocms_snippet", "SnippetPtr") - - # Iterate over the queryset, create a grouper for each instance which doesn't have one - # and map the content objects foreign key field to it. - for snippet in Snippet.objects.all(): - if not snippet.snippet_grouper: - create_groupers(snippet, SnippetGrouper) - grouper_count += 1 - - logger.info(f"SnippetPlugin count pre-migration: {SnippetPtr.objects.all().count()}") - # Iterate over the plugin queryset, and replace them each with a CMS4 plugin - for snippet_plugin in SnippetPtr.objects.all(): - _create_plugin(snippet_plugin, snippet_plugin.new_snippet, SnippetPtr) - plugin_count += 1 - - logger.info(f"Migration completed, created {grouper_count} Snippet Groupers and {plugin_count} Snippet plugins") - - -class Migration(migrations.Migration): - - dependencies = [ - ('djangocms_snippet', '0009_auto_20210831_0715'), - ] - - operations = [ - migrations.RunPython(cms4_migration) - ] From 225b9f9e016279d88d920d20aff4574f8b36abab Mon Sep 17 00:00:00 2001 From: Adam Murray Date: Mon, 6 Sep 2021 17:17:51 +0100 Subject: [PATCH 022/107] Implemented proper plugin migration --- ...10_cms4_grouper_version_data_migration.py} | 0 .../0011_cms4_plugin_data_migration.py | 30 +++++++++++++++++++ 2 files changed, 30 insertions(+) rename djangocms_snippet/migrations/{0010_cms4_grouper_version_migration.py => 0010_cms4_grouper_version_data_migration.py} (100%) create mode 100644 djangocms_snippet/migrations/0011_cms4_plugin_data_migration.py diff --git a/djangocms_snippet/migrations/0010_cms4_grouper_version_migration.py b/djangocms_snippet/migrations/0010_cms4_grouper_version_data_migration.py similarity index 100% rename from djangocms_snippet/migrations/0010_cms4_grouper_version_migration.py rename to djangocms_snippet/migrations/0010_cms4_grouper_version_data_migration.py diff --git a/djangocms_snippet/migrations/0011_cms4_plugin_data_migration.py b/djangocms_snippet/migrations/0011_cms4_plugin_data_migration.py new file mode 100644 index 00000000..ee38de4b --- /dev/null +++ b/djangocms_snippet/migrations/0011_cms4_plugin_data_migration.py @@ -0,0 +1,30 @@ +# Generated by Django 2.2.24 on 2021-08-31 10:45 +import logging +from django.db import migrations + + +logger = logging.getLogger(__name__) + + +def cms4_migration(apps, schema_editor): + plugin_count = 0 + SnippetPtr = apps.get_model("djangocms_snippet", "SnippetPtr") + + for snippet_plugin in SnippetPtr.objects.all(): + snippet = snippet_plugin.snippet + grouper = snippet.snippet_grouper + snippet_plugin.new_snippet = grouper + snippet_plugin.save() + plugin_count += 1 + logger.info(f"Migration completed, created {plugin_count} Snippet plugins") + + +class Migration(migrations.Migration): + + dependencies = [ + ('djangocms_snippet', '0010_cms4_grouper_version_data_migration'), + ] + + operations = [ + migrations.RunPython(cms4_migration) + ] From 500cf7249cc38848c06c5bdf38fb2c12c2ff1904 Mon Sep 17 00:00:00 2001 From: Adam Murray Date: Mon, 6 Sep 2021 17:20:59 +0100 Subject: [PATCH 023/107] Removed management command --- djangocms_snippet/management/__init__.py | 0 .../management/commands/__init__.py | 0 .../commands/cms4_data_migration.py | 59 ------------------- 3 files changed, 59 deletions(-) delete mode 100644 djangocms_snippet/management/__init__.py delete mode 100644 djangocms_snippet/management/commands/__init__.py delete mode 100644 djangocms_snippet/management/commands/cms4_data_migration.py diff --git a/djangocms_snippet/management/__init__.py b/djangocms_snippet/management/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/djangocms_snippet/management/commands/__init__.py b/djangocms_snippet/management/commands/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/djangocms_snippet/management/commands/cms4_data_migration.py b/djangocms_snippet/management/commands/cms4_data_migration.py deleted file mode 100644 index f137c3cd..00000000 --- a/djangocms_snippet/management/commands/cms4_data_migration.py +++ /dev/null @@ -1,59 +0,0 @@ -import logging - -from django.conf import settings -from django.contrib.auth.models import User -from django.contrib.contenttypes.models import ContentType -from django.core.management.base import BaseCommand -from django.db import transaction - -from djangocms_snippet.models import Snippet, SnippetGrouper, SnippetPtr -from djangocms_versioning.constants import DRAFT -from djangocms_versioning.models import Version - - -logger = logging.getLogger(__name__) - - -class Command(BaseCommand): - help = 'Command to migrate cms3 model structure into cms4 by creating relevant Groupers and Versions' - - def _create_version(self, snippet, state=DRAFT, number=1): - # Get a migration user. - migration_user = getattr(settings, "DJANGOCMS_SNIPPET_VERSIONING_MIGRATION_USER_ID", None) - if not migration_user: - logger.warning( - "Setting DJANGOCMS_SNIPPET_VERSIONING_MIGRATION_USER_ID not provided, defaulting to user id: 1" - ) - migration_user = User.objects.get(id=1) - - # The contenttype of the content model - snippet_contenttype = ContentType.objects.get(app_label='djangocms_snippet', model='snippet') - - logger.info("Creating version for new grouper: {}".format(snippet.pk)) - # Create a new version for the snippet - Version.objects.create( - created_by=migration_user, - state=state, - number=number, - object_id=snippet.pk, - content_type=snippet_contenttype, - ) - - def handle(self, *args, **options): - # The queryset of populated models. - queryset = Snippet._base_manager.all() - - # Since we are doing a database migration, use an atomic transaction - with transaction.atomic(): - version_count = 0 - - for snippet in queryset: - # If there are no versions of this content, create one. - if hasattr(snippet, "versions"): - if not snippet.versions.all(): - self._create_version(snippet=snippet) - version_count += 1 - - logger.info( - f"Created {version_count} version objects" - ) From 2017d9013a912265dced723aded3dde66ce19d51 Mon Sep 17 00:00:00 2001 From: Adam Murray Date: Tue, 7 Sep 2021 08:47:37 +0100 Subject: [PATCH 024/107] Migration 10 now handles lack of versioning gracefully. --- ...010_cms4_grouper_version_data_migration.py | 36 ++++++++++--------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/djangocms_snippet/migrations/0010_cms4_grouper_version_data_migration.py b/djangocms_snippet/migrations/0010_cms4_grouper_version_data_migration.py index 3c6a8fa7..cdafa318 100644 --- a/djangocms_snippet/migrations/0010_cms4_grouper_version_data_migration.py +++ b/djangocms_snippet/migrations/0010_cms4_grouper_version_data_migration.py @@ -1,13 +1,17 @@ import logging -import settings +import os from django.db import migrations -# TODO: Remove this -from djangocms_versioning.constants import DRAFT logger = logging.getLogger(__name__) +try: + from djangocms_versioning.constants import DRAFT + djangocsm_versioning_enabled = True +except: + djangocsm_versioning_enabled = False + def cms4_grouper_version_migration(apps, schema_editor): grouper_count = 0 @@ -17,7 +21,6 @@ def cms4_grouper_version_migration(apps, schema_editor): Snippet = apps.get_model("djangocms_snippet", "Snippet") SnippetGrouper = apps.get_model("djangocms_snippet", "SnippetGrouper") User = apps.get_model('auth', 'User') - Version = apps.get_model("djangocms_versioning", "Version") snippet_contenttype = ContentType.objects.get(app_label='djangocms_snippet', model='snippet') snippet_queryset = Snippet.objects.all() @@ -30,24 +33,25 @@ def cms4_grouper_version_migration(apps, schema_editor): grouper_count += 1 # Get a migration user. - # TODO: Use environment variable, fall back to setting, then to default - migration_user = getattr(settings, "DJANGOCMS_SNIPPET_VERSIONING_MIGRATION_USER_ID", None) + migration_user = os.environ.get("DJANGOCMS_SNIPPET_VERSIONING_MIGRATION_USER_ID", None) if not migration_user: logger.warning( "Setting DJANGOCMS_SNIPPET_VERSIONING_MIGRATION_USER_ID not provided, defaulting to user id: 1" ) migration_user = User.objects.get(id=1) - version = Version.objects.create( - created_by=migration_user, - state=DRAFT, - number=1, - object_id=snippet.pk, - content_type=snippet_contenttype, - ) - logger.info(f"Created Snippet Version ID: {version.pk}") - # This will be necessary when versioning checks are implemented - version_count += 1 + if djangocsm_versioning_enabled: + Version = apps.get_model("djangocms_versioning", "Version") + version = Version.objects.create( + created_by=migration_user, + state=DRAFT, + number=1, + object_id=snippet.pk, + content_type=snippet_contenttype, + ) + logger.info(f"Created Snippet Version ID: {version.pk}") + # This will be necessary when versioning checks are implemented + version_count += 1 logger.info(f"Migration created {grouper_count} SnippetGrouper models and {version_count} Version models") From 25e552ee6c932af85f79fb0cf8db05f3f9f13c65 Mon Sep 17 00:00:00 2001 From: Adam Murray Date: Tue, 7 Sep 2021 12:27:52 +0100 Subject: [PATCH 025/107] Add snippet property for backwards compatibility Co-authored-by: Aiky30 --- djangocms_snippet/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/djangocms_snippet/models.py b/djangocms_snippet/models.py index 42fac2f9..6394c5a7 100644 --- a/djangocms_snippet/models.py +++ b/djangocms_snippet/models.py @@ -74,7 +74,7 @@ class SnippetPtr(CMSPlugin): ) snippet = models.ForeignKey(Snippet, on_delete=models.CASCADE) - new_snippet = models.ForeignKey(SnippetGrouper, on_delete=models.CASCADE) + snippet_grouper = models.ForeignKey(SnippetGrouper, on_delete=models.CASCADE) search_fields = ['snippet__html'] if SEARCH_ENABLED else [] From 59f82a8eee1bcf4203f5ed4f4be056934fe28424 Mon Sep 17 00:00:00 2001 From: Adam Murray Date: Tue, 7 Sep 2021 12:29:22 +0100 Subject: [PATCH 026/107] Remove old foreign key from plugin, and rename new one --- .../0012_remove_snippetptr_snippet.py | 17 +++++++++++++++++ .../0013_rename_snippetptr_new_snippet_0624.py | 18 ++++++++++++++++++ djangocms_snippet/models.py | 4 +--- 3 files changed, 36 insertions(+), 3 deletions(-) create mode 100644 djangocms_snippet/migrations/0012_remove_snippetptr_snippet.py create mode 100644 djangocms_snippet/migrations/0013_rename_snippetptr_new_snippet_0624.py diff --git a/djangocms_snippet/migrations/0012_remove_snippetptr_snippet.py b/djangocms_snippet/migrations/0012_remove_snippetptr_snippet.py new file mode 100644 index 00000000..b91adf76 --- /dev/null +++ b/djangocms_snippet/migrations/0012_remove_snippetptr_snippet.py @@ -0,0 +1,17 @@ +# Generated by Django 2.2.24 on 2021-09-07 06:22 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('djangocms_snippet', '0011_cms4_plugin_data_migration'), + ] + + operations = [ + migrations.RemoveField( + model_name='snippetptr', + name='snippet', + ), + ] diff --git a/djangocms_snippet/migrations/0013_rename_snippetptr_new_snippet_0624.py b/djangocms_snippet/migrations/0013_rename_snippetptr_new_snippet_0624.py new file mode 100644 index 00000000..431aa76f --- /dev/null +++ b/djangocms_snippet/migrations/0013_rename_snippetptr_new_snippet_0624.py @@ -0,0 +1,18 @@ +# Generated by Django 2.2.24 on 2021-09-07 06:24 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('djangocms_snippet', '0012_remove_snippetptr_snippet'), + ] + + operations = [ + migrations.RenameField( + model_name='snippetptr', + old_name='new_snippet', + new_name='snippet', + ), + ] diff --git a/djangocms_snippet/models.py b/djangocms_snippet/models.py index 42fac2f9..93182fc9 100644 --- a/djangocms_snippet/models.py +++ b/djangocms_snippet/models.py @@ -72,9 +72,7 @@ class SnippetPtr(CMSPlugin): parent_link=True, on_delete=models.CASCADE, ) - - snippet = models.ForeignKey(Snippet, on_delete=models.CASCADE) - new_snippet = models.ForeignKey(SnippetGrouper, on_delete=models.CASCADE) + snippet = models.ForeignKey(SnippetGrouper, on_delete=models.CASCADE) search_fields = ['snippet__html'] if SEARCH_ENABLED else [] From 25048ff182c1f0847a5b1746f8d0a8dbe00e2ad1 Mon Sep 17 00:00:00 2001 From: Adam Murray Date: Tue, 7 Sep 2021 13:46:11 +0100 Subject: [PATCH 027/107] Cleaned up migration and models --- djangocms_snippet/conf.py | 5 ++++ ...010_cms4_grouper_version_data_migration.py | 24 +++---------------- .../migrations/0012_auto_20210907_0654.py | 22 +++++++++++++++++ djangocms_snippet/models.py | 6 +++-- 4 files changed, 34 insertions(+), 23 deletions(-) create mode 100644 djangocms_snippet/conf.py create mode 100644 djangocms_snippet/migrations/0012_auto_20210907_0654.py diff --git a/djangocms_snippet/conf.py b/djangocms_snippet/conf.py new file mode 100644 index 00000000..f65d33d0 --- /dev/null +++ b/djangocms_snippet/conf.py @@ -0,0 +1,5 @@ +from django.conf import settings + +DJANGOCMS_SNIPPET_VERSIONING_MIGRATION_USER_ID = getattr( + settings, "DJANGOCMS_SNIPPET_VERSIONING_MIGRATION_USER_ID", 1 +) diff --git a/djangocms_snippet/migrations/0010_cms4_grouper_version_data_migration.py b/djangocms_snippet/migrations/0010_cms4_grouper_version_data_migration.py index cdafa318..17b9ce85 100644 --- a/djangocms_snippet/migrations/0010_cms4_grouper_version_data_migration.py +++ b/djangocms_snippet/migrations/0010_cms4_grouper_version_data_migration.py @@ -1,10 +1,6 @@ -import logging -import os - from django.db import migrations - -logger = logging.getLogger(__name__) +from djangocms_snippet.conf import DJANGOCMS_SNIPPET_VERSIONING_MIGRATION_USER_ID try: from djangocms_versioning.constants import DRAFT @@ -14,9 +10,6 @@ def cms4_grouper_version_migration(apps, schema_editor): - grouper_count = 0 - version_count = 0 - ContentType = apps.get_model("contenttypes", "ContentType") Snippet = apps.get_model("djangocms_snippet", "Snippet") SnippetGrouper = apps.get_model("djangocms_snippet", "SnippetGrouper") @@ -29,31 +22,20 @@ def cms4_grouper_version_migration(apps, schema_editor): grouper = SnippetGrouper.objects.create() snippet.new_snippet = grouper snippet.save() - logger.info(f"Created Snippet Grouper ID: {snippet.snippet_grouper}") - grouper_count += 1 # Get a migration user. - migration_user = os.environ.get("DJANGOCMS_SNIPPET_VERSIONING_MIGRATION_USER_ID", None) - if not migration_user: - logger.warning( - "Setting DJANGOCMS_SNIPPET_VERSIONING_MIGRATION_USER_ID not provided, defaulting to user id: 1" - ) - migration_user = User.objects.get(id=1) + migration_user = User.objects.get(id=DJANGOCMS_SNIPPET_VERSIONING_MIGRATION_USER_ID) if djangocsm_versioning_enabled: Version = apps.get_model("djangocms_versioning", "Version") - version = Version.objects.create( + Version.objects.create( created_by=migration_user, state=DRAFT, number=1, object_id=snippet.pk, content_type=snippet_contenttype, ) - logger.info(f"Created Snippet Version ID: {version.pk}") # This will be necessary when versioning checks are implemented - version_count += 1 - - logger.info(f"Migration created {grouper_count} SnippetGrouper models and {version_count} Version models") class Migration(migrations.Migration): diff --git a/djangocms_snippet/migrations/0012_auto_20210907_0654.py b/djangocms_snippet/migrations/0012_auto_20210907_0654.py new file mode 100644 index 00000000..6c4f31be --- /dev/null +++ b/djangocms_snippet/migrations/0012_auto_20210907_0654.py @@ -0,0 +1,22 @@ +# Generated by Django 2.2.24 on 2021-09-07 06:54 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('djangocms_snippet', '0011_cms4_plugin_data_migration'), + ] + + operations = [ + migrations.RenameField( + model_name='snippetptr', + old_name='new_snippet', + new_name='snippet_grouper', + ), + migrations.RemoveField( + model_name='snippetptr', + name='snippet', + ), + ] diff --git a/djangocms_snippet/models.py b/djangocms_snippet/models.py index 6394c5a7..bf7703a9 100644 --- a/djangocms_snippet/models.py +++ b/djangocms_snippet/models.py @@ -72,8 +72,6 @@ class SnippetPtr(CMSPlugin): parent_link=True, on_delete=models.CASCADE, ) - - snippet = models.ForeignKey(Snippet, on_delete=models.CASCADE) snippet_grouper = models.ForeignKey(SnippetGrouper, on_delete=models.CASCADE) search_fields = ['snippet__html'] if SEARCH_ENABLED else [] @@ -82,6 +80,10 @@ class Meta: verbose_name = _('Snippet Ptr') verbose_name_plural = _('Snippet Ptrs') + @property + def snippet(self): + return self.snippet_grouper.snippet_set.first() + def __str__(self): # Return the referenced snippet's name rather than the default (ID #) return self.snippet.name From 649c4af1538100a5601df696d601392fae497088 Mon Sep 17 00:00:00 2001 From: Adam Murray Date: Tue, 7 Sep 2021 13:47:10 +0100 Subject: [PATCH 028/107] Removed unecessary logging --- .../migrations/0011_cms4_plugin_data_migration.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/djangocms_snippet/migrations/0011_cms4_plugin_data_migration.py b/djangocms_snippet/migrations/0011_cms4_plugin_data_migration.py index ee38de4b..3b52a547 100644 --- a/djangocms_snippet/migrations/0011_cms4_plugin_data_migration.py +++ b/djangocms_snippet/migrations/0011_cms4_plugin_data_migration.py @@ -1,11 +1,7 @@ # Generated by Django 2.2.24 on 2021-08-31 10:45 -import logging from django.db import migrations -logger = logging.getLogger(__name__) - - def cms4_migration(apps, schema_editor): plugin_count = 0 SnippetPtr = apps.get_model("djangocms_snippet", "SnippetPtr") @@ -16,7 +12,6 @@ def cms4_migration(apps, schema_editor): snippet_plugin.new_snippet = grouper snippet_plugin.save() plugin_count += 1 - logger.info(f"Migration completed, created {plugin_count} Snippet plugins") class Migration(migrations.Migration): From bc8d60e9674e099ef4363a22eb51779070946f8b Mon Sep 17 00:00:00 2001 From: Adam Murray Date: Tue, 7 Sep 2021 14:33:02 +0100 Subject: [PATCH 029/107] Remove redundent comment --- .../migrations/0010_cms4_grouper_version_data_migration.py | 1 - 1 file changed, 1 deletion(-) diff --git a/djangocms_snippet/migrations/0010_cms4_grouper_version_data_migration.py b/djangocms_snippet/migrations/0010_cms4_grouper_version_data_migration.py index 17b9ce85..9c628403 100644 --- a/djangocms_snippet/migrations/0010_cms4_grouper_version_data_migration.py +++ b/djangocms_snippet/migrations/0010_cms4_grouper_version_data_migration.py @@ -35,7 +35,6 @@ def cms4_grouper_version_migration(apps, schema_editor): object_id=snippet.pk, content_type=snippet_contenttype, ) - # This will be necessary when versioning checks are implemented class Migration(migrations.Migration): From 4103082e4b5bd5e7b544abcd0f8f5952e20e0efa Mon Sep 17 00:00:00 2001 From: Adam Murray Date: Tue, 7 Sep 2021 15:39:49 +0100 Subject: [PATCH 030/107] Update djangocms_snippet/migrations/0010_cms4_grouper_version_data_migration.py Co-authored-by: Aiky30 --- .../migrations/0010_cms4_grouper_version_data_migration.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/djangocms_snippet/migrations/0010_cms4_grouper_version_data_migration.py b/djangocms_snippet/migrations/0010_cms4_grouper_version_data_migration.py index 9c628403..a07eae02 100644 --- a/djangocms_snippet/migrations/0010_cms4_grouper_version_data_migration.py +++ b/djangocms_snippet/migrations/0010_cms4_grouper_version_data_migration.py @@ -4,7 +4,7 @@ try: from djangocms_versioning.constants import DRAFT - djangocsm_versioning_enabled = True + djangocms_versioning_enabled = True except: djangocsm_versioning_enabled = False From ad25ec89658b6b5d326f6c9c6d29f6f94f4b8456 Mon Sep 17 00:00:00 2001 From: Adam Murray Date: Tue, 7 Sep 2021 15:39:58 +0100 Subject: [PATCH 031/107] Update djangocms_snippet/migrations/0010_cms4_grouper_version_data_migration.py Co-authored-by: Aiky30 --- .../migrations/0010_cms4_grouper_version_data_migration.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/djangocms_snippet/migrations/0010_cms4_grouper_version_data_migration.py b/djangocms_snippet/migrations/0010_cms4_grouper_version_data_migration.py index a07eae02..c9617a60 100644 --- a/djangocms_snippet/migrations/0010_cms4_grouper_version_data_migration.py +++ b/djangocms_snippet/migrations/0010_cms4_grouper_version_data_migration.py @@ -6,7 +6,7 @@ from djangocms_versioning.constants import DRAFT djangocms_versioning_enabled = True except: - djangocsm_versioning_enabled = False + djangocms_versioning_enabled = False def cms4_grouper_version_migration(apps, schema_editor): From 929d9d6299bc5ac3d89088ea899d79fad109a4d1 Mon Sep 17 00:00:00 2001 From: Adam Murray Date: Tue, 7 Sep 2021 15:40:07 +0100 Subject: [PATCH 032/107] Update djangocms_snippet/migrations/0011_cms4_plugin_data_migration.py Co-authored-by: Aiky30 --- djangocms_snippet/migrations/0011_cms4_plugin_data_migration.py | 1 - 1 file changed, 1 deletion(-) diff --git a/djangocms_snippet/migrations/0011_cms4_plugin_data_migration.py b/djangocms_snippet/migrations/0011_cms4_plugin_data_migration.py index 3b52a547..4b3d635f 100644 --- a/djangocms_snippet/migrations/0011_cms4_plugin_data_migration.py +++ b/djangocms_snippet/migrations/0011_cms4_plugin_data_migration.py @@ -3,7 +3,6 @@ def cms4_migration(apps, schema_editor): - plugin_count = 0 SnippetPtr = apps.get_model("djangocms_snippet", "SnippetPtr") for snippet_plugin in SnippetPtr.objects.all(): From 8e624d980b9d09df616bf22ca63cd4f7a2b9ee27 Mon Sep 17 00:00:00 2001 From: Adam Murray Date: Tue, 7 Sep 2021 15:40:17 +0100 Subject: [PATCH 033/107] Update djangocms_snippet/conf.py Co-authored-by: Aiky30 --- djangocms_snippet/conf.py | 1 + 1 file changed, 1 insertion(+) diff --git a/djangocms_snippet/conf.py b/djangocms_snippet/conf.py index f65d33d0..b4dc989e 100644 --- a/djangocms_snippet/conf.py +++ b/djangocms_snippet/conf.py @@ -1,5 +1,6 @@ from django.conf import settings + DJANGOCMS_SNIPPET_VERSIONING_MIGRATION_USER_ID = getattr( settings, "DJANGOCMS_SNIPPET_VERSIONING_MIGRATION_USER_ID", 1 ) From f7c848e739e5aa05674b3d619cda9baa146119d5 Mon Sep 17 00:00:00 2001 From: Adam Murray Date: Tue, 7 Sep 2021 15:40:38 +0100 Subject: [PATCH 034/107] Update djangocms_snippet/migrations/0011_cms4_plugin_data_migration.py Co-authored-by: Aiky30 --- djangocms_snippet/migrations/0011_cms4_plugin_data_migration.py | 1 - 1 file changed, 1 deletion(-) diff --git a/djangocms_snippet/migrations/0011_cms4_plugin_data_migration.py b/djangocms_snippet/migrations/0011_cms4_plugin_data_migration.py index 4b3d635f..098736f4 100644 --- a/djangocms_snippet/migrations/0011_cms4_plugin_data_migration.py +++ b/djangocms_snippet/migrations/0011_cms4_plugin_data_migration.py @@ -10,7 +10,6 @@ def cms4_migration(apps, schema_editor): grouper = snippet.snippet_grouper snippet_plugin.new_snippet = grouper snippet_plugin.save() - plugin_count += 1 class Migration(migrations.Migration): From 85f96f2ca626ea75ca10813a06b7191336ad426c Mon Sep 17 00:00:00 2001 From: Adam Murray Date: Tue, 7 Sep 2021 17:23:38 +0100 Subject: [PATCH 035/107] Fixed variable name spelling mistake --- .../migrations/0010_cms4_grouper_version_data_migration.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/djangocms_snippet/migrations/0010_cms4_grouper_version_data_migration.py b/djangocms_snippet/migrations/0010_cms4_grouper_version_data_migration.py index 9c628403..129be8d7 100644 --- a/djangocms_snippet/migrations/0010_cms4_grouper_version_data_migration.py +++ b/djangocms_snippet/migrations/0010_cms4_grouper_version_data_migration.py @@ -4,9 +4,9 @@ try: from djangocms_versioning.constants import DRAFT - djangocsm_versioning_enabled = True + djangocms_versioning_enabled = True except: - djangocsm_versioning_enabled = False + djangocms_versioning_enabled = False def cms4_grouper_version_migration(apps, schema_editor): @@ -26,7 +26,7 @@ def cms4_grouper_version_migration(apps, schema_editor): # Get a migration user. migration_user = User.objects.get(id=DJANGOCMS_SNIPPET_VERSIONING_MIGRATION_USER_ID) - if djangocsm_versioning_enabled: + if djangocms_versioning_enabled: Version = apps.get_model("djangocms_versioning", "Version") Version.objects.create( created_by=migration_user, From bea0a0a4921e454a6a9285d8fc7ead63c645f03e Mon Sep 17 00:00:00 2001 From: Adam Murray Date: Tue, 7 Sep 2021 17:27:29 +0100 Subject: [PATCH 036/107] Use util --- .../0010_cms4_grouper_version_data_migration.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/djangocms_snippet/migrations/0010_cms4_grouper_version_data_migration.py b/djangocms_snippet/migrations/0010_cms4_grouper_version_data_migration.py index 129be8d7..13b19ace 100644 --- a/djangocms_snippet/migrations/0010_cms4_grouper_version_data_migration.py +++ b/djangocms_snippet/migrations/0010_cms4_grouper_version_data_migration.py @@ -1,12 +1,10 @@ from django.db import migrations from djangocms_snippet.conf import DJANGOCMS_SNIPPET_VERSIONING_MIGRATION_USER_ID +from djangocms_snippet.utils import is_versioning_enabled -try: +if is_versioning_enabled(): from djangocms_versioning.constants import DRAFT - djangocms_versioning_enabled = True -except: - djangocms_versioning_enabled = False def cms4_grouper_version_migration(apps, schema_editor): @@ -26,7 +24,7 @@ def cms4_grouper_version_migration(apps, schema_editor): # Get a migration user. migration_user = User.objects.get(id=DJANGOCMS_SNIPPET_VERSIONING_MIGRATION_USER_ID) - if djangocms_versioning_enabled: + if is_versioning_enabled: Version = apps.get_model("djangocms_versioning", "Version") Version.objects.create( created_by=migration_user, From 980822654b723de32f96ba72d1c92a795b04c702 Mon Sep 17 00:00:00 2001 From: Adam Murray Date: Tue, 7 Sep 2021 17:47:33 +0100 Subject: [PATCH 037/107] Updated linting in migrations, and versioning enabled check --- ...010_cms4_grouper_version_data_migration.py | 19 ++++++++++++------- .../0011_cms4_plugin_data_migration.py | 2 +- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/djangocms_snippet/migrations/0010_cms4_grouper_version_data_migration.py b/djangocms_snippet/migrations/0010_cms4_grouper_version_data_migration.py index 13b19ace..21df822f 100644 --- a/djangocms_snippet/migrations/0010_cms4_grouper_version_data_migration.py +++ b/djangocms_snippet/migrations/0010_cms4_grouper_version_data_migration.py @@ -1,16 +1,21 @@ from django.db import migrations from djangocms_snippet.conf import DJANGOCMS_SNIPPET_VERSIONING_MIGRATION_USER_ID -from djangocms_snippet.utils import is_versioning_enabled -if is_versioning_enabled(): +try: from djangocms_versioning.constants import DRAFT + djangocms_versioning_installed = True +except ImportError: + djangocms_versioning_installed = False def cms4_grouper_version_migration(apps, schema_editor): - ContentType = apps.get_model("contenttypes", "ContentType") - Snippet = apps.get_model("djangocms_snippet", "Snippet") - SnippetGrouper = apps.get_model("djangocms_snippet", "SnippetGrouper") + app_config = apps.get_app_config('djangocms_snippet') + djangocms_versioning_config_enabled = app_config.cms_config.djangocms_versioning_enabled + + ContentType = apps.get_model('contenttypes', 'ContentType') + Snippet = apps.get_model('djangocms_snippet', 'Snippet') + SnippetGrouper = apps.get_model('djangocms_snippet', 'SnippetGrouper') User = apps.get_model('auth', 'User') snippet_contenttype = ContentType.objects.get(app_label='djangocms_snippet', model='snippet') @@ -24,8 +29,8 @@ def cms4_grouper_version_migration(apps, schema_editor): # Get a migration user. migration_user = User.objects.get(id=DJANGOCMS_SNIPPET_VERSIONING_MIGRATION_USER_ID) - if is_versioning_enabled: - Version = apps.get_model("djangocms_versioning", "Version") + if djangocms_versioning_config_enabled and djangocms_versioning_installed: + Version = apps.get_model('djangocms_versioning', 'Version') Version.objects.create( created_by=migration_user, state=DRAFT, diff --git a/djangocms_snippet/migrations/0011_cms4_plugin_data_migration.py b/djangocms_snippet/migrations/0011_cms4_plugin_data_migration.py index 098736f4..632559f1 100644 --- a/djangocms_snippet/migrations/0011_cms4_plugin_data_migration.py +++ b/djangocms_snippet/migrations/0011_cms4_plugin_data_migration.py @@ -3,7 +3,7 @@ def cms4_migration(apps, schema_editor): - SnippetPtr = apps.get_model("djangocms_snippet", "SnippetPtr") + SnippetPtr = apps.get_model('djangocms_snippet', 'SnippetPtr') for snippet_plugin in SnippetPtr.objects.all(): snippet = snippet_plugin.snippet From 530e416440b1ab2834ae69176c1326ed9288f692 Mon Sep 17 00:00:00 2001 From: Adam Murray Date: Tue, 7 Sep 2021 18:04:50 +0100 Subject: [PATCH 038/107] Added instructions for DJANGOCMS_SNIPPET_VERSIONING_MIGRATION_USER_ID to README --- README.rst | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.rst b/README.rst index 60bec6a6..16ddf714 100644 --- a/README.rst +++ b/README.rst @@ -80,6 +80,11 @@ please set ``DJANGOCMS_SNIPPET_CACHE`` to ``False`` in your settings:: DJANGOCMS_SNIPPET_CACHE = False # default value is True +Migration 0010 requires the use of a user in order to create versions for existing snippets, a user can be +chosen with the setting ``DJANGOCMS_SNIPPET_VERSIONING_MIGRATION_USER_ID`` + + DJANGOCMS_SNIPPET_VERSIONING_MIGRATION_USER_ID = 1 # Will use user with id: 1 + Template tag ------------ From a3cdc9b21048886308aa8cb74770ac24caa5070b Mon Sep 17 00:00:00 2001 From: Adam Murray Date: Tue, 7 Sep 2021 18:05:48 +0100 Subject: [PATCH 039/107] Added instructions for DJANGOCMS_SNIPPET_VERSIONING_MIGRATION_USER_ID to README --- README.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.rst b/README.rst index 16ddf714..6bdbe290 100644 --- a/README.rst +++ b/README.rst @@ -81,9 +81,9 @@ please set ``DJANGOCMS_SNIPPET_CACHE`` to ``False`` in your settings:: DJANGOCMS_SNIPPET_CACHE = False # default value is True Migration 0010 requires the use of a user in order to create versions for existing snippets, a user can be -chosen with the setting ``DJANGOCMS_SNIPPET_VERSIONING_MIGRATION_USER_ID`` +chosen with the setting ``DJANGOCMS_SNIPPET_VERSIONING_MIGRATION_USER_ID``, the default is 1 - DJANGOCMS_SNIPPET_VERSIONING_MIGRATION_USER_ID = 1 # Will use user with id: 1 + DJANGOCMS_SNIPPET_VERSIONING_MIGRATION_USER_ID = 2 # Will use user with id: 2 Template tag ------------ From ce96a1f40e0816aefc5eb74ed7dd41d1cd09ae4d Mon Sep 17 00:00:00 2001 From: Adam Murray Date: Tue, 7 Sep 2021 18:07:18 +0100 Subject: [PATCH 040/107] Added instructions for DJANGOCMS_SNIPPET_VERSIONING_MIGRATION_USER_ID to README --- README.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.rst b/README.rst index 6bdbe290..6cedd459 100644 --- a/README.rst +++ b/README.rst @@ -80,8 +80,8 @@ please set ``DJANGOCMS_SNIPPET_CACHE`` to ``False`` in your settings:: DJANGOCMS_SNIPPET_CACHE = False # default value is True -Migration 0010 requires the use of a user in order to create versions for existing snippets, a user can be -chosen with the setting ``DJANGOCMS_SNIPPET_VERSIONING_MIGRATION_USER_ID``, the default is 1 +Migration 0010 requires the use of a user in order to create versions for existing snippets (if djangocms_versioning is installed and enabled), +a user can be chosen with the setting ``DJANGOCMS_SNIPPET_VERSIONING_MIGRATION_USER_ID``, the default is 1. DJANGOCMS_SNIPPET_VERSIONING_MIGRATION_USER_ID = 2 # Will use user with id: 2 From c696c67a2d5e5cd4e1f0c6585e5bf373509a3ba5 Mon Sep 17 00:00:00 2001 From: Adam Murray Date: Tue, 7 Sep 2021 18:16:43 +0100 Subject: [PATCH 041/107] isort --- djangocms_snippet/cms_config.py | 8 +++++--- djangocms_snippet/migrations/0009_auto_20210831_0715.py | 2 +- .../0010_cms4_grouper_version_data_migration.py | 5 ++++- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/djangocms_snippet/cms_config.py b/djangocms_snippet/cms_config.py index 9c4ed1b3..00f9bae9 100644 --- a/djangocms_snippet/cms_config.py +++ b/djangocms_snippet/cms_config.py @@ -1,7 +1,7 @@ -from cms.app_base import CMSAppConfig - from django.conf import settings +from cms.app_base import CMSAppConfig + from .models import Snippet @@ -10,7 +10,9 @@ class SnippetCMSAppConfig(CMSAppConfig): settings, 'DJANGOCMS_SNIPPET_VERSIONING_ENABLED', True) if djangocms_versioning_enabled: - from djangocms_versioning.datastructures import VersionableItem, default_copy + from djangocms_versioning.datastructures import ( + VersionableItem, default_copy, + ) versioning = [ VersionableItem( diff --git a/djangocms_snippet/migrations/0009_auto_20210831_0715.py b/djangocms_snippet/migrations/0009_auto_20210831_0715.py index 09a033b5..95f4b05f 100644 --- a/djangocms_snippet/migrations/0009_auto_20210831_0715.py +++ b/djangocms_snippet/migrations/0009_auto_20210831_0715.py @@ -1,7 +1,7 @@ # Generated by Django 2.2.24 on 2021-08-31 07:15 -from django.db import migrations, models import django.db.models.deletion +from django.db import migrations, models class Migration(migrations.Migration): diff --git a/djangocms_snippet/migrations/0010_cms4_grouper_version_data_migration.py b/djangocms_snippet/migrations/0010_cms4_grouper_version_data_migration.py index 21df822f..bfd0069a 100644 --- a/djangocms_snippet/migrations/0010_cms4_grouper_version_data_migration.py +++ b/djangocms_snippet/migrations/0010_cms4_grouper_version_data_migration.py @@ -1,6 +1,9 @@ from django.db import migrations -from djangocms_snippet.conf import DJANGOCMS_SNIPPET_VERSIONING_MIGRATION_USER_ID +from djangocms_snippet.conf import ( + DJANGOCMS_SNIPPET_VERSIONING_MIGRATION_USER_ID, +) + try: from djangocms_versioning.constants import DRAFT From 3e3b736afef3e6afc8d02780778b26653e75756e Mon Sep 17 00:00:00 2001 From: Adam Murray Date: Tue, 7 Sep 2021 18:31:40 +0100 Subject: [PATCH 042/107] Removed unecessary plugin --- djangocms_snippet/cms_config.py | 4 ++-- djangocms_snippet/cms_plugins.py | 23 +++++------------------ 2 files changed, 7 insertions(+), 20 deletions(-) diff --git a/djangocms_snippet/cms_config.py b/djangocms_snippet/cms_config.py index 6b7bb65b..ac56d30c 100644 --- a/djangocms_snippet/cms_config.py +++ b/djangocms_snippet/cms_config.py @@ -1,7 +1,7 @@ -from cms.app_base import CMSAppConfig, CMSAppExtension - from django.conf import settings +from cms.app_base import CMSAppConfig, CMSAppExtension + from djangocms_versioning.datastructures import VersionableItem, default_copy from .models import Snippet diff --git a/djangocms_snippet/cms_plugins.py b/djangocms_snippet/cms_plugins.py index 48da0f9e..bf432da9 100644 --- a/djangocms_snippet/cms_plugins.py +++ b/djangocms_snippet/cms_plugins.py @@ -7,16 +7,14 @@ from cms.plugin_base import CMSPluginBase from cms.plugin_pool import plugin_pool -from .models import SnippetPluginModel, SnippetPtr -from .utils import is_versioning_enabled +from .models import SnippetPtr -CACHE_ENABLED = getattr(settings, "DJANGOCMS_SNIPPET_CACHE", False) +CACHE_ENABLED = getattr(settings, "DJANGOCMS_SNIPPET_CACHE", False) -class AbstractSnippetPlugin(CMSPluginBase): - class Meta: - abstract = True +class SnippetPlugin(CMSPluginBase): + model = SnippetPtr name = _("Snippet") render_template = "djangocms_snippet/snippet.html" text_enabled = True @@ -53,15 +51,4 @@ def render(self, context, instance, placeholder): return context -class SnippetPlugin(AbstractSnippetPlugin): - model = SnippetPtr - - -class VersionedSnippetPlugin(AbstractSnippetPlugin): - model = SnippetPluginModel - - -if is_versioning_enabled: - plugin_pool.register_plugin(VersionedSnippetPlugin) -else: - plugin_pool.register_plugin(SnippetPlugin) +plugin_pool.register_plugin(SnippetPlugin) From 1aec683c1f5e8d3cafdd2f97d4d091452258470a Mon Sep 17 00:00:00 2001 From: Adam Murray Date: Tue, 7 Sep 2021 18:56:08 +0100 Subject: [PATCH 043/107] Changed to version4 python version compatibility in test suite --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 1b4f6752..65d334c7 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -8,7 +8,7 @@ jobs: strategy: fail-fast: false matrix: - python-version: [ 3.7, 3.8, 3.9, ] # latest release minus two + python-version: [ 3.6, 3.7, ] requirements-file: [ dj22_cms37.txt, dj22_cms38.txt, From 53609d26d245b9590b1e4e1545b0f8a524f157aa Mon Sep 17 00:00:00 2001 From: Adam Murray Date: Wed, 8 Sep 2021 10:17:02 +0100 Subject: [PATCH 044/107] Updated to cms4 based test suite --- .github/workflows/test.yml | 7 ++----- tests/requirements/dj11_cms40.txt | 4 ++++ 2 files changed, 6 insertions(+), 5 deletions(-) create mode 100644 tests/requirements/dj11_cms40.txt diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 65d334c7..a3bf1414 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -10,11 +10,8 @@ jobs: matrix: python-version: [ 3.6, 3.7, ] requirements-file: [ - dj22_cms37.txt, - dj22_cms38.txt, - dj30_cms37.txt, - dj30_cms38.txt, - dj31_cms38.txt, + dj11_cms40.txt, + dj22_cms40.txt, ] os: [ ubuntu-20.04, diff --git a/tests/requirements/dj11_cms40.txt b/tests/requirements/dj11_cms40.txt new file mode 100644 index 00000000..4c9d6c95 --- /dev/null +++ b/tests/requirements/dj11_cms40.txt @@ -0,0 +1,4 @@ +-r base.txt + +https://github.com/django-cms/django-cms/tarball/release/4.0.x#egg=django-cms +https://github.com/divio/djangocms-versioning/tarball/master/#egg=djangocms-versioning From 8dfb6dbb5500536458b3aad68a37114adfda5042 Mon Sep 17 00:00:00 2001 From: Adam Murray Date: Wed, 8 Sep 2021 10:38:55 +0100 Subject: [PATCH 045/107] Removed redundent abstract model --- djangocms_snippet/models.py | 24 ++++++++---------------- 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/djangocms_snippet/models.py b/djangocms_snippet/models.py index 7e6f8d7d..83c18a38 100644 --- a/djangocms_snippet/models.py +++ b/djangocms_snippet/models.py @@ -60,33 +60,25 @@ class Meta: # Plugin model - just a pointer to Snippet -class AbstractSnippetPluginModel(CMSPlugin): +class SnippetPtr(CMSPlugin): # Add an app namespace to related_name to avoid field name clashes # with any other plugins that have a field with the same name as the # lowercase of the class name of this model. # https://github.com/divio/django-cms/issues/5030 + cmsplugin_ptr = models.OneToOneField( + CMSPlugin, + related_name='%(app_label)s_%(class)s', + parent_link=True, + on_delete=models.CASCADE, + ) + snippet = models.ForeignKey(Snippet, on_delete=models.CASCADE) search_fields = ['snippet__html'] if SEARCH_ENABLED else [] class Meta: verbose_name = _('Snippet Ptr') verbose_name_plural = _('Snippet Ptrs') - abstract = True def __str__(self): # Return the referenced snippet's name rather than the default (ID #) return self.snippet.name - - -class SnippetPluginModel(AbstractSnippetPluginModel): - snippet = models.ForeignKey(SnippetGrouper, on_delete=models.CASCADE, ) - - -class SnippetPtr(AbstractSnippetPluginModel): - cmsplugin_ptr = models.OneToOneField( - CMSPlugin, - related_name='%(app_label)s_%(class)s', - parent_link=True, - on_delete=models.CASCADE, - ) - snippet = models.ForeignKey(Snippet, on_delete=models.CASCADE) From ff5d6356ac08c16446532d244a438ceffee978da Mon Sep 17 00:00:00 2001 From: Adam Murray Date: Wed, 8 Sep 2021 11:05:37 +0100 Subject: [PATCH 046/107] Fixed app config issue --- .../migrations/0010_cms4_grouper_version_data_migration.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/djangocms_snippet/migrations/0010_cms4_grouper_version_data_migration.py b/djangocms_snippet/migrations/0010_cms4_grouper_version_data_migration.py index bfd0069a..2616cbd4 100644 --- a/djangocms_snippet/migrations/0010_cms4_grouper_version_data_migration.py +++ b/djangocms_snippet/migrations/0010_cms4_grouper_version_data_migration.py @@ -3,7 +3,7 @@ from djangocms_snippet.conf import ( DJANGOCMS_SNIPPET_VERSIONING_MIGRATION_USER_ID, ) - +from djangocms_snippet.cms_config import SnippetCMSAppConfig try: from djangocms_versioning.constants import DRAFT @@ -13,8 +13,7 @@ def cms4_grouper_version_migration(apps, schema_editor): - app_config = apps.get_app_config('djangocms_snippet') - djangocms_versioning_config_enabled = app_config.cms_config.djangocms_versioning_enabled + djangocms_versioning_config_enabled = SnippetCMSAppConfig.djangocms_versioning_enabled ContentType = apps.get_model('contenttypes', 'ContentType') Snippet = apps.get_model('djangocms_snippet', 'Snippet') From c2f62de9bf7087a9882f885c68e007bca6608c89 Mon Sep 17 00:00:00 2001 From: Adam Murray Date: Wed, 8 Sep 2021 11:11:08 +0100 Subject: [PATCH 047/107] Removed unused management command --- djangocms_snippet/management/__init__.py | 0 .../management/cms4_data_migration.py | 57 ------------------- 2 files changed, 57 deletions(-) delete mode 100644 djangocms_snippet/management/__init__.py delete mode 100644 djangocms_snippet/management/cms4_data_migration.py diff --git a/djangocms_snippet/management/__init__.py b/djangocms_snippet/management/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/djangocms_snippet/management/cms4_data_migration.py b/djangocms_snippet/management/cms4_data_migration.py deleted file mode 100644 index 78c5aa3a..00000000 --- a/djangocms_snippet/management/cms4_data_migration.py +++ /dev/null @@ -1,57 +0,0 @@ -import logging - -from django.core.management.base import BaseCommand, CommandError - -from django.conf import settings -from django.contrib.auth.models import User -from django.contrib.contenttypes.models import ContentType - -from djangocms_versioning.models import Version - -from djangocms_snippet.models import Snippet, SnippetGrouper - -from djangocms_versioning.constants import DRAFT - - -logger = logging.getLogger(__name__) - - -class Command(BaseCommand): - help = 'Command to migrate cms3 model structure into cms4 by creating relevant Groupers and Versions' - - def _create_version(snippet, state=DRAFT, number=1): - # Get a migration user. - migration_user = getattr(settings, "DJANGOCMS_SNIPPET_VERSIONING_MIGRATION_USER_ID", None) - # The contenttype of the content model - snippet_contenttype = ContentType.objects.get(app_label='djangocms_snippet', model='snippet') - - if not migration_user: - logger.warning( - "Setting DJANGOCMS_SNIPPET_VERSIONING_MIGRATION_USER_ID not provided, defaulting to user id: 1" - ) - migration_user = User.objects.get(id=1) - - logger.info("Creating version for new grouper: {}".format(snippet.pk)) - - # Create a new version for the snippet - Version.objects.create( - created_by=migration_user, - state=state, - number=number, - object_id=snippet.pk, - content_type=snippet_contenttype, - ) - - def handle(self, *args, **options): - # The queryset of populate models. - queryset = Snippet.objects.all() - - # Iterate over the queryset, create a grouper for each instance - # and map the content objects foreign key field to it. - for snippet in queryset: - if not snippet.snippet_grouper: - grouper = SnippetGrouper.objects.create() - snippet.snippet_grouper = grouper - snippet.save() - if not snippet.versions.all(): - self._create_version(snippet) From ef314fbddb09bc2a8a989ad6367392edfbee6707 Mon Sep 17 00:00:00 2001 From: Adam Murray Date: Wed, 8 Sep 2021 11:11:38 +0100 Subject: [PATCH 048/107] Removed management command --- djangocms_snippet/management/__init__.py | 0 .../management/cms4_data_migration.py | 57 ------------------- 2 files changed, 57 deletions(-) delete mode 100644 djangocms_snippet/management/__init__.py delete mode 100644 djangocms_snippet/management/cms4_data_migration.py diff --git a/djangocms_snippet/management/__init__.py b/djangocms_snippet/management/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/djangocms_snippet/management/cms4_data_migration.py b/djangocms_snippet/management/cms4_data_migration.py deleted file mode 100644 index 78c5aa3a..00000000 --- a/djangocms_snippet/management/cms4_data_migration.py +++ /dev/null @@ -1,57 +0,0 @@ -import logging - -from django.core.management.base import BaseCommand, CommandError - -from django.conf import settings -from django.contrib.auth.models import User -from django.contrib.contenttypes.models import ContentType - -from djangocms_versioning.models import Version - -from djangocms_snippet.models import Snippet, SnippetGrouper - -from djangocms_versioning.constants import DRAFT - - -logger = logging.getLogger(__name__) - - -class Command(BaseCommand): - help = 'Command to migrate cms3 model structure into cms4 by creating relevant Groupers and Versions' - - def _create_version(snippet, state=DRAFT, number=1): - # Get a migration user. - migration_user = getattr(settings, "DJANGOCMS_SNIPPET_VERSIONING_MIGRATION_USER_ID", None) - # The contenttype of the content model - snippet_contenttype = ContentType.objects.get(app_label='djangocms_snippet', model='snippet') - - if not migration_user: - logger.warning( - "Setting DJANGOCMS_SNIPPET_VERSIONING_MIGRATION_USER_ID not provided, defaulting to user id: 1" - ) - migration_user = User.objects.get(id=1) - - logger.info("Creating version for new grouper: {}".format(snippet.pk)) - - # Create a new version for the snippet - Version.objects.create( - created_by=migration_user, - state=state, - number=number, - object_id=snippet.pk, - content_type=snippet_contenttype, - ) - - def handle(self, *args, **options): - # The queryset of populate models. - queryset = Snippet.objects.all() - - # Iterate over the queryset, create a grouper for each instance - # and map the content objects foreign key field to it. - for snippet in queryset: - if not snippet.snippet_grouper: - grouper = SnippetGrouper.objects.create() - snippet.snippet_grouper = grouper - snippet.save() - if not snippet.versions.all(): - self._create_version(snippet) From 0ad68fec36c277154cd4c7d8dd387e1ef77b10cd Mon Sep 17 00:00:00 2001 From: Adam Murray Date: Wed, 8 Sep 2021 15:39:40 +0100 Subject: [PATCH 049/107] Updates snippet tests for cms4 --- djangocms_snippet/utils.py | 10 ---------- tests/test_configuration.py | 22 ---------------------- tests/test_plugins.py | 20 +++++++++----------- 3 files changed, 9 insertions(+), 43 deletions(-) delete mode 100644 djangocms_snippet/utils.py delete mode 100644 tests/test_configuration.py diff --git a/djangocms_snippet/utils.py b/djangocms_snippet/utils.py deleted file mode 100644 index 91f48a2f..00000000 --- a/djangocms_snippet/utils.py +++ /dev/null @@ -1,10 +0,0 @@ -from django.apps import apps - - -def is_versioning_enabled(): - from .models import Snippet - try: - app_config = apps.get_app_config('djangocms_versioning') - return app_config.cms_extension.is_content_model_versioned(Snippet) - except LookupError: - return False diff --git a/tests/test_configuration.py b/tests/test_configuration.py deleted file mode 100644 index 0c262c22..00000000 --- a/tests/test_configuration.py +++ /dev/null @@ -1,22 +0,0 @@ -from django.conf import settings -from django.test import TestCase, override_settings - -from djangocms_snippet.utils import is_versioning_enabled - - -class VersioningConfigurationTestCase(TestCase): - - @override_settings(DJANGOCMS_SNIPPET_VERSIONING_ENABLED=True) - def test_versioning_enabled_with_setting_config(self): - # Check getattr returns correct value - self.assertTrue(getattr(settings, 'DJANGOCMS_SNIPPET_VERSIONING_ENABLED')) - - # Check util is working - self.assertTrue(is_versioning_enabled()) - - def test_versioning_disabled_without_setting_config(self): - # Check getattr returns None if setting is not configured - self.assertIsNone(getattr(settings, 'DJANGOCMS_SNIPPET_VERSIONING_ENABLED', None)) - - # Util should return false - self.assertFalse(is_versioning_enabled()) diff --git a/tests/test_plugins.py b/tests/test_plugins.py index 6e4e6767..c0bfa487 100644 --- a/tests/test_plugins.py +++ b/tests/test_plugins.py @@ -12,15 +12,16 @@ def setUp(self): title="home", template="page.html", language=self.language, + published=True, ) - self.home.publish(self.language) self.page = create_page( title="help", template="page.html", language=self.language, + published=True, ) - self.page.publish(self.language) - self.placeholder = self.page.placeholders.get(slot="content") + self.pagecontent = self.page.pagecontent_set.first() + self.placeholder = self.pagecontent.placeholders.get(slot="content") self.superuser = self.get_superuser() def tearDown(self): @@ -36,12 +37,12 @@ def test_html_rendering(self): slug="plugin_snippet", ) plugin = add_plugin( - self.page.placeholders.get(slot="content"), + self.pagecontent.placeholders.get(slot="content"), "SnippetPlugin", self.language, snippet=snippet, ) - self.page.publish(self.language) + self.assertEqual(plugin.snippet.name, "plugin_snippet") self.assertEqual(plugin.snippet.html, "

Hello World

") self.assertEqual(plugin.snippet.slug, "plugin_snippet") @@ -59,12 +60,11 @@ def test_failing_html_rendering(self): slug="plugin_snippet", ) add_plugin( - self.page.placeholders.get(slot="content"), + self.pagecontent.placeholders.get(slot="content"), "SnippetPlugin", self.language, snippet=snippet, ) - self.page.publish(self.language) with self.login_user_context(self.superuser): response = self.client.get(request_url) @@ -82,12 +82,11 @@ def test_template_rendering(self): ) snippet.save() plugin = add_plugin( - self.page.placeholders.get(slot="content"), + self.pagecontent.placeholders.get(slot="content"), "SnippetPlugin", self.language, snippet=snippet, ) - self.page.publish(self.language) self.assertEqual(plugin.snippet.name, "plugin_snippet") self.assertEqual(plugin.snippet.slug, "plugin_snippet") @@ -109,12 +108,11 @@ def test_failing_template_rendering(self): ) snippet.save() add_plugin( - self.page.placeholders.get(slot="content"), + self.pagecontent.placeholders.get(slot="content"), "SnippetPlugin", self.language, snippet=snippet, ) - self.page.publish(self.language) with self.login_user_context(self.superuser): response = self.client.get(request_url) From f3943a3e695c71b3332302a1faee9e623db996df Mon Sep 17 00:00:00 2001 From: Adam Murray Date: Wed, 8 Sep 2021 15:46:25 +0100 Subject: [PATCH 050/107] linting --- djangocms_snippet/cms_config.py | 8 +++++--- djangocms_snippet/migrations/0009_auto_20210811_0942.py | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/djangocms_snippet/cms_config.py b/djangocms_snippet/cms_config.py index 5264c557..cf87874d 100644 --- a/djangocms_snippet/cms_config.py +++ b/djangocms_snippet/cms_config.py @@ -1,7 +1,7 @@ -from cms.app_base import CMSAppConfig - from django.conf import settings +from cms.app_base import CMSAppConfig + from .models import Snippet @@ -11,7 +11,9 @@ class SnippetCMSAppConfig(CMSAppConfig): ) if djangocms_versioning_enabled: - from djangocms_versioning.datastructures import VersionableItem, default_copy + from djangocms_versioning.datastructures import ( + VersionableItem, default_copy, + ) versioning = [ VersionableItem( diff --git a/djangocms_snippet/migrations/0009_auto_20210811_0942.py b/djangocms_snippet/migrations/0009_auto_20210811_0942.py index 4f7e5cb8..2107cc34 100644 --- a/djangocms_snippet/migrations/0009_auto_20210811_0942.py +++ b/djangocms_snippet/migrations/0009_auto_20210811_0942.py @@ -1,7 +1,7 @@ # Generated by Django 2.2.24 on 2021-08-11 09:42 -from django.db import migrations, models import django.db.models.deletion +from django.db import migrations, models class Migration(migrations.Migration): From a08485e2bbd9da65139c689d22ef95358719f5ce Mon Sep 17 00:00:00 2001 From: Adam Murray Date: Wed, 8 Sep 2021 15:57:39 +0100 Subject: [PATCH 051/107] Removed unecessary published flag on page creation --- tests/test_plugins.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/test_plugins.py b/tests/test_plugins.py index c0bfa487..2e971d10 100644 --- a/tests/test_plugins.py +++ b/tests/test_plugins.py @@ -12,13 +12,11 @@ def setUp(self): title="home", template="page.html", language=self.language, - published=True, ) self.page = create_page( title="help", template="page.html", language=self.language, - published=True, ) self.pagecontent = self.page.pagecontent_set.first() self.placeholder = self.pagecontent.placeholders.get(slot="content") From 736b9755130149f7739beca6bfc09aafc9d66fad Mon Sep 17 00:00:00 2001 From: Adam Murray Date: Thu, 9 Sep 2021 10:23:58 +0100 Subject: [PATCH 052/107] Push for testing --- tests/settings.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/settings.py b/tests/settings.py index 5656cebe..bc942c2a 100644 --- a/tests/settings.py +++ b/tests/settings.py @@ -2,6 +2,7 @@ HELPER_SETTINGS = { 'INSTALLED_APPS': [ 'tests.utils', + 'djangocms_snippet', ], 'CMS_LANGUAGES': { 1: [{ From 9dd25637b4b44d99bee03cfb8d7f12cd4b5e9739 Mon Sep 17 00:00:00 2001 From: Adam Murray Date: Thu, 9 Sep 2021 10:25:58 +0100 Subject: [PATCH 053/107] Updates to tests --- .../migrations/0010_cms4_grouper_version_data_migration.py | 2 -- tests/test_plugins.py | 1 + 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/djangocms_snippet/migrations/0010_cms4_grouper_version_data_migration.py b/djangocms_snippet/migrations/0010_cms4_grouper_version_data_migration.py index 1d5ba56e..2616cbd4 100644 --- a/djangocms_snippet/migrations/0010_cms4_grouper_version_data_migration.py +++ b/djangocms_snippet/migrations/0010_cms4_grouper_version_data_migration.py @@ -20,8 +20,6 @@ def cms4_grouper_version_migration(apps, schema_editor): SnippetGrouper = apps.get_model('djangocms_snippet', 'SnippetGrouper') User = apps.get_model('auth', 'User') - import pdb - pdb.set_trace() snippet_contenttype = ContentType.objects.get(app_label='djangocms_snippet', model='snippet') snippet_queryset = Snippet.objects.all() diff --git a/tests/test_plugins.py b/tests/test_plugins.py index 2e971d10..30fca4e0 100644 --- a/tests/test_plugins.py +++ b/tests/test_plugins.py @@ -29,6 +29,7 @@ def tearDown(self): def test_html_rendering(self): request_url = self.page.get_absolute_url(self.language) + "?toolbar_off=true" + # snippet = Snippet.objects.create( name="plugin_snippet", html="

Hello World

", From 96035a3809611667e3774809bf2265249f552833 Mon Sep 17 00:00:00 2001 From: Adam Murray Date: Fri, 10 Sep 2021 12:02:49 +0100 Subject: [PATCH 054/107] Added factories, fixed model tests and templatetag tests --- ...831_0715.py => 0009_auto_20210909_0901.py} | 16 +- ...010_cms4_grouper_version_data_migration.py | 16 +- ...907_0654.py => 0012_auto_20210909_0912.py} | 15 +- tests/settings.py | 2 + tests/test_models.py | 40 ++-- tests/test_templatetags.py | 34 ++-- tests/utils/__init__.py | 1 + tests/utils/factories.py | 188 ++++++++++++++++++ tests/utils/utils.py | 14 ++ 9 files changed, 269 insertions(+), 57 deletions(-) rename djangocms_snippet/migrations/{0009_auto_20210831_0715.py => 0009_auto_20210909_0901.py} (67%) rename djangocms_snippet/migrations/{0012_auto_20210907_0654.py => 0012_auto_20210909_0912.py} (50%) create mode 100644 tests/utils/factories.py create mode 100644 tests/utils/utils.py diff --git a/djangocms_snippet/migrations/0009_auto_20210831_0715.py b/djangocms_snippet/migrations/0009_auto_20210909_0901.py similarity index 67% rename from djangocms_snippet/migrations/0009_auto_20210831_0715.py rename to djangocms_snippet/migrations/0009_auto_20210909_0901.py index 95f4b05f..28e717d7 100644 --- a/djangocms_snippet/migrations/0009_auto_20210831_0715.py +++ b/djangocms_snippet/migrations/0009_auto_20210909_0901.py @@ -1,7 +1,7 @@ -# Generated by Django 2.2.24 on 2021-08-31 07:15 +# Generated by Django 2.2.24 on 2021-09-09 09:01 -import django.db.models.deletion from django.db import migrations, models +import django.db.models.deletion class Migration(migrations.Migration): @@ -17,16 +17,6 @@ class Migration(migrations.Migration): ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ], ), - migrations.AlterField( - model_name='snippet', - name='name', - field=models.CharField(max_length=255, verbose_name='Name'), - ), - migrations.AlterField( - model_name='snippet', - name='slug', - field=models.SlugField(default='', max_length=255, verbose_name='Slug'), - ), migrations.AddField( model_name='snippet', name='snippet_grouper', @@ -34,7 +24,7 @@ class Migration(migrations.Migration): ), migrations.AddField( model_name='snippetptr', - name='new_snippet', + name='snippet_grouper', field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='djangocms_snippet.SnippetGrouper'), ), ] diff --git a/djangocms_snippet/migrations/0010_cms4_grouper_version_data_migration.py b/djangocms_snippet/migrations/0010_cms4_grouper_version_data_migration.py index 2616cbd4..619ae8d2 100644 --- a/djangocms_snippet/migrations/0010_cms4_grouper_version_data_migration.py +++ b/djangocms_snippet/migrations/0010_cms4_grouper_version_data_migration.py @@ -1,18 +1,25 @@ +from django.apps import apps as global_apps +from django.contrib.contenttypes.management import create_contenttypes from django.db import migrations +from djangocms_snippet.cms_config import SnippetCMSAppConfig from djangocms_snippet.conf import ( DJANGOCMS_SNIPPET_VERSIONING_MIGRATION_USER_ID, ) -from djangocms_snippet.cms_config import SnippetCMSAppConfig + try: from djangocms_versioning.constants import DRAFT + djangocms_versioning_installed = True except ImportError: djangocms_versioning_installed = False def cms4_grouper_version_migration(apps, schema_editor): + # TODO: Remove + create_contenttypes(global_apps.get_app_config("djangocms_snippet")) + djangocms_versioning_config_enabled = SnippetCMSAppConfig.djangocms_versioning_enabled ContentType = apps.get_model('contenttypes', 'ContentType') @@ -43,11 +50,14 @@ def cms4_grouper_version_migration(apps, schema_editor): class Migration(migrations.Migration): - dependencies = [ - ('djangocms_snippet', '0009_auto_20210831_0715'), + ('cms', '0034_remove_pagecontent_placeholders'), # Run after the CMS4 migrations + ('djangocms_snippet', '0009_auto_20210909_0901'), ] + if djangocms_versioning_installed: + dependencies += [('djangocms_versioning', '0015_version_modified'), ] + operations = [ migrations.RunPython(cms4_grouper_version_migration) ] diff --git a/djangocms_snippet/migrations/0012_auto_20210907_0654.py b/djangocms_snippet/migrations/0012_auto_20210909_0912.py similarity index 50% rename from djangocms_snippet/migrations/0012_auto_20210907_0654.py rename to djangocms_snippet/migrations/0012_auto_20210909_0912.py index 6c4f31be..5f8a8cd6 100644 --- a/djangocms_snippet/migrations/0012_auto_20210907_0654.py +++ b/djangocms_snippet/migrations/0012_auto_20210909_0912.py @@ -1,6 +1,7 @@ -# Generated by Django 2.2.24 on 2021-09-07 06:54 +# Generated by Django 2.2.24 on 2021-09-09 09:12 -from django.db import migrations +from django.db import migrations, models +import django.db.models.deletion class Migration(migrations.Migration): @@ -10,13 +11,13 @@ class Migration(migrations.Migration): ] operations = [ - migrations.RenameField( - model_name='snippetptr', - old_name='new_snippet', - new_name='snippet_grouper', - ), migrations.RemoveField( model_name='snippetptr', name='snippet', ), + migrations.AlterField( + model_name='snippetptr', + name='snippet_grouper', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='djangocms_snippet.SnippetGrouper'), + ), ] diff --git a/tests/settings.py b/tests/settings.py index bc942c2a..23c4edd3 100644 --- a/tests/settings.py +++ b/tests/settings.py @@ -2,6 +2,7 @@ HELPER_SETTINGS = { 'INSTALLED_APPS': [ 'tests.utils', + 'djangocms_versioning', 'djangocms_snippet', ], 'CMS_LANGUAGES': { @@ -12,6 +13,7 @@ }, 'LANGUAGE_CODE': 'en', 'ALLOWED_HOSTS': ['localhost'], + 'DJANGOCMS_SNIPPET_VERSIONING_ENABLED': True, } diff --git a/tests/test_models.py b/tests/test_models.py index 077e0010..c1e2b039 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -1,28 +1,35 @@ -from django.test import TestCase +from cms.test_utils.testcases import CMSTestCase from djangocms_snippet.models import SEARCH_ENABLED, Snippet, SnippetPtr +from .utils.factories import ( + SnippetPluginFactory, + SnippetWithVersionFactory, +) -class SnippetModelTestCase(TestCase): - def setUp(self): - pass +class SnippetModelTestCase(CMSTestCase): - def tearDown(self): - pass + def setUp(self): + self.snippet = SnippetWithVersionFactory( + name="test snippet", + html="

hello world

", + slug="test_snippet", + ) + self.snippet.versions.last().publish(user=self.get_superuser()) + self.snippet_grouper = self.snippet.snippet_grouper + SnippetPluginFactory(snippet_grouper=self.snippet_grouper, language=["en"]) def test_settings(self): self.assertEqual(SEARCH_ENABLED, False) def test_snippet_instance(self): - Snippet.objects.create( - name="test snippet", - html="

hello world

", - slug="test_snippet", - ) instance = Snippet.objects.all() + self.assertEqual(instance.count(), 1) + instance = Snippet.objects.first() + self.assertEqual(instance.name, "test snippet") self.assertEqual(instance.html, "

hello world

") self.assertEqual(instance.slug, "test_snippet") @@ -30,16 +37,11 @@ def test_snippet_instance(self): self.assertEqual(str(instance), "test snippet") def test_snippet_ptr_instance(self): - snippet = Snippet.objects.create( - name="test snippet", - html="

hello world

", - slug="test_snippet", - ) - SnippetPtr.objects.create( - snippet=snippet, - ) instance = SnippetPtr.objects.all() + self.assertEqual(instance.count(), 1) + instance = SnippetPtr.objects.first() + # test strings self.assertEqual(str(instance), "test snippet") diff --git a/tests/test_templatetags.py b/tests/test_templatetags.py index b1bb45b5..468a7408 100644 --- a/tests/test_templatetags.py +++ b/tests/test_templatetags.py @@ -1,22 +1,23 @@ from django.core.exceptions import ObjectDoesNotExist from django.template import Context, Template from django.template.exceptions import TemplateSyntaxError -from django.test import TestCase -from djangocms_snippet.models import Snippet, SnippetPtr +from cms.test_utils.testcases import CMSTestCase +from .utils.factories import SnippetPluginFactory, SnippetWithVersionFactory -class SnippetTemplateTagTestCase(TestCase): + +class SnippetTemplateTagTestCase(CMSTestCase): def test_html_rendered(self): - snippet = Snippet.objects.create( + snippet = SnippetWithVersionFactory( name="test snippet", html="

hello {{ title }}

", slug="test_snippet", ) - SnippetPtr.objects.create( - snippet=snippet, - ) + snippet.versions.last().publish(user=self.get_superuser()) + snippet_grouper = snippet.snippet_grouper + SnippetPluginFactory(snippet_grouper=snippet_grouper, language=["en"]) context = Context({"title": "world"}) template_to_render = Template( @@ -24,6 +25,7 @@ def test_html_rendered(self): '{% snippet_fragment "test_snippet" %}' ) rendered_template = template_to_render.render(context) + self.assertInHTML('

hello world

', rendered_template) # test html errors @@ -38,14 +40,15 @@ def test_html_rendered(self): def test_template_rendered(self): template = "snippet.html" - snippet = Snippet.objects.create( + snippet = SnippetWithVersionFactory( name="test snippet", + html="

hello {{ title }}

", template=template, slug="test_snippet", ) - SnippetPtr.objects.create( - snippet=snippet, - ) + snippet.versions.last().publish(user=self.get_superuser()) + snippet_grouper = snippet.snippet_grouper + SnippetPluginFactory(snippet_grouper=snippet_grouper, language=["en"]) # use a string to identify context = Context({}) @@ -76,14 +79,15 @@ def test_template_rendered(self): def test_template_errors(self): template = "does_not_exist.html" - snippet = Snippet.objects.create( + snippet = SnippetWithVersionFactory( name="test snippet", + html="

hello {{ title }}

", template=template, slug="test_snippet", ) - SnippetPtr.objects.create( - snippet=snippet, - ) + snippet.versions.last().publish(user=self.get_superuser()) + snippet_grouper = snippet.snippet_grouper + SnippetPluginFactory(snippet_grouper=snippet_grouper, language=["en"]) context = Context({}) template_to_render = Template( diff --git a/tests/utils/__init__.py b/tests/utils/__init__.py index e69de29b..8b137891 100644 --- a/tests/utils/__init__.py +++ b/tests/utils/__init__.py @@ -0,0 +1 @@ + diff --git a/tests/utils/factories.py b/tests/utils/factories.py new file mode 100644 index 00000000..5e993505 --- /dev/null +++ b/tests/utils/factories.py @@ -0,0 +1,188 @@ +import string + +from django.contrib.auth.models import User +from django.contrib.contenttypes.models import ContentType +from django.contrib.sites.models import Site + +from cms import constants +from cms.models import Page, PageContent, PageUrl, Placeholder, TreeNode + +import factory +from factory.fuzzy import FuzzyChoice, FuzzyInteger, FuzzyText + +from djangocms_versioning.models import Version + +from djangocms_snippet.models import ( + Snippet, + SnippetGrouper, + SnippetPtr +) + + +class PlaceholderFactory(factory.django.DjangoModelFactory): + default_width = FuzzyInteger(0, 25) + slot = FuzzyText(length=2, chars=string.digits) + # NOTE: When using this factory you will probably want to set + # the source field manually + + class Meta: + model = Placeholder + + +class UserFactory(factory.django.DjangoModelFactory): + username = FuzzyText(length=12) + first_name = factory.Faker("first_name") + last_name = factory.Faker("last_name") + email = factory.LazyAttribute( + lambda u: "%s.%s@example.com" % (u.first_name.lower(), u.last_name.lower()) + ) + + class Meta: + model = User + + @classmethod + def _create(cls, model_class, *args, **kwargs): + """Override the default ``_create`` with our custom call.""" + manager = cls._get_manager(model_class) + # The default would use ``manager.create(*args, **kwargs)`` + return manager.create_user(*args, **kwargs) + + +class AbstractVersionFactory(factory.django.DjangoModelFactory): + object_id = factory.SelfAttribute("content.id") + content_type = factory.LazyAttribute( + lambda o: ContentType.objects.get_for_model(o.content) + ) + created_by = factory.SubFactory(UserFactory) + + class Meta: + exclude = ["content"] + abstract = True + + +class TreeNodeFactory(factory.django.DjangoModelFactory): + site = factory.fuzzy.FuzzyChoice(Site.objects.all()) + depth = 0 + # NOTE: Generating path this way is probably not a good way of + # doing it, but seems to work for our present tests which only + # really need a tree node to exist and not throw unique constraint + # errors on this field. If the data in this model starts mattering + # in our tests then something more will need to be done here. + path = FuzzyText(length=8, chars=string.digits) + + class Meta: + model = TreeNode + + +class PageFactory(factory.django.DjangoModelFactory): + node = factory.SubFactory(TreeNodeFactory) + + class Meta: + model = Page + + +class PageContentFactory(factory.django.DjangoModelFactory): + page = factory.SubFactory(PageFactory) + language = FuzzyChoice(["en", "fr", "it"]) + title = FuzzyText(length=12) + page_title = FuzzyText(length=12) + menu_title = FuzzyText(length=12) + meta_description = FuzzyText(length=12) + redirect = FuzzyText(length=12) + created_by = FuzzyText(length=12) + changed_by = FuzzyText(length=12) + in_navigation = FuzzyChoice([True, False]) + soft_root = FuzzyChoice([True, False]) + limit_visibility_in_menu = constants.VISIBILITY_USERS + template = 'page.html' + xframe_options = FuzzyInteger(0, 25) + + class Meta: + model = PageContent + + +class PageVersionFactory(AbstractVersionFactory): + content = factory.SubFactory(PageContentFactory) + + class Meta: + model = Version + + +class PageContentWithVersionFactory(PageContentFactory): + @factory.post_generation + def version(self, create, extracted, **kwargs): + # NOTE: Use this method as below to define version attributes: + # PageContentWithVersionFactory(version__label='label1') + if not create: + # Simple build, do nothing. + return + PageVersionFactory(content=self, **kwargs) + + +class SnippetGrouperFactory(factory.django.DjangoModelFactory): + + class Meta: + model = SnippetGrouper + + +class AbstractSnippetFactory(factory.django.DjangoModelFactory): + name = FuzzyText(length=12) + slug = FuzzyText(length=12) + snippet_grouper = factory.SubFactory(SnippetGrouperFactory) + + class Meta: + abstract = True + + +class SnippetFactory(AbstractSnippetFactory): + class Meta: + model = Snippet + + +class SnippetVersionFactory(AbstractVersionFactory): + content = factory.SubFactory(SnippetFactory) + + class Meta: + model = Version + + +class SnippetWithVersionFactory(AbstractSnippetFactory): + @factory.post_generation + def version(self, create, extracted, **kwargs): + # NOTE: Use this method as below to define version attributes: + # PageContentWithVersionFactory(version__label='label1') + if not create: + # Simple build, do nothing. + return + SnippetVersionFactory(content=self, **kwargs) + + class Meta: + model = Snippet + + +def get_plugin_position(plugin): + """Helper function to correctly calculate the plugin position. + Use this in plugin factory classes + """ + offset = plugin.placeholder.get_last_plugin_position(plugin.language) or 0 + return offset + 1 + + +def get_plugin_language(plugin): + """Helper function to get the language from a plugin's relationships. + Use this in plugin factory classes + """ + if plugin.placeholder.source: + return plugin.placeholder.source.language + + +class SnippetPluginFactory(factory.django.DjangoModelFactory): + plugin_type = "SnippetPlugin" + parent = None + snippet_grouper = factory.SubFactory(SnippetGrouperFactory) + placeholder = factory.SubFactory(PlaceholderFactory) + position = factory.LazyAttribute(get_plugin_position) + language = factory.LazyAttribute(get_plugin_language) + + class Meta: + model = SnippetPtr diff --git a/tests/utils/utils.py b/tests/utils/utils.py new file mode 100644 index 00000000..1dabc21c --- /dev/null +++ b/tests/utils/utils.py @@ -0,0 +1,14 @@ +from djangocms_snippet.cms_config import SnippetCMSAppConfig + +try: + from djangocms_versioning import __version__ + versioning_installed = True +except ImportError: + versioning_installed = False + + +def is_versioning_enabled(): + if SnippetCMSAppConfig.djangocms_versioning_enabled and versioning_installed: + return True + else: + return False From 5b65538dcee5a6af9a3cb06d83565781e4977cfe Mon Sep 17 00:00:00 2001 From: Adam Murray Date: Fri, 10 Sep 2021 13:17:13 +0100 Subject: [PATCH 055/107] Updated plugin tests --- tests/requirements/base.txt | 1 + tests/test_plugins.py | 72 +++++++++++++++++++++++-------------- 2 files changed, 46 insertions(+), 27 deletions(-) diff --git a/tests/requirements/base.txt b/tests/requirements/base.txt index 77fedde3..2ea5f4f9 100644 --- a/tests/requirements/base.txt +++ b/tests/requirements/base.txt @@ -3,3 +3,4 @@ tox coverage isort flake8 +factory-boy diff --git a/tests/test_plugins.py b/tests/test_plugins.py index 30fca4e0..5382daf5 100644 --- a/tests/test_plugins.py +++ b/tests/test_plugins.py @@ -1,45 +1,57 @@ from cms.api import add_plugin, create_page +from cms.models import PageContent from cms.test_utils.testcases import CMSTestCase -from djangocms_snippet.models import Snippet +from djangocms_snippet.models import Snippet, SnippetGrouper + + +from .utils.factories import ( + PageContentWithVersionFactory, + SnippetPluginFactory, + SnippetWithVersionFactory, +) + class SnippetPluginsTestCase(CMSTestCase): def setUp(self): self.language = "en" - self.home = create_page( - title="home", - template="page.html", - language=self.language, - ) - self.page = create_page( - title="help", - template="page.html", - language=self.language, - ) - self.pagecontent = self.page.pagecontent_set.first() - self.placeholder = self.pagecontent.placeholders.get(slot="content") self.superuser = self.get_superuser() - - def tearDown(self): - self.page.delete() - self.home.delete() - self.superuser.delete() + page_data = { + "title": "home", + "template": "page.html", + "language": self.language, + } + + self.home_pagecontent = PageContentWithVersionFactory(**page_data) + self.home = self.home_pagecontent.page + page_data["title"] = "help" + self.pagecontent = PageContentWithVersionFactory(**page_data) + self.page = self.pagecontent.page + self.pagecontent.versions.first().publish(user=self.superuser) + self.page.save() + + self.placeholder = self.pagecontent.placeholders.create(slot="content") def test_html_rendering(self): request_url = self.page.get_absolute_url(self.language) + "?toolbar_off=true" - # - snippet = Snippet.objects.create( + + snippet = SnippetWithVersionFactory( name="plugin_snippet", html="

Hello World

", slug="plugin_snippet", ) + snippet_grouper = snippet.snippet_grouper + # SnippetPluginFactory(snippet_grouper=snippet_grouper, language=["en"]) + + snippet.versions.last().publish(user=self.get_superuser()) + plugin = add_plugin( self.pagecontent.placeholders.get(slot="content"), "SnippetPlugin", self.language, - snippet=snippet, + snippet_grouper=snippet_grouper, ) self.assertEqual(plugin.snippet.name, "plugin_snippet") @@ -53,16 +65,19 @@ def test_html_rendering(self): def test_failing_html_rendering(self): request_url = self.page.get_absolute_url(self.language) + "?toolbar_off=true" - snippet = Snippet.objects.create( + snippet_grouper = SnippetGrouper.objects.create() + + Snippet.objects.create( name="plugin_snippet", html="{% import weirdness %}", slug="plugin_snippet", + snippet_grouper=snippet_grouper ) add_plugin( self.pagecontent.placeholders.get(slot="content"), "SnippetPlugin", self.language, - snippet=snippet, + snippet_grouper=snippet_grouper, ) with self.login_user_context(self.superuser): @@ -72,8 +87,9 @@ def test_failing_html_rendering(self): self.assertContains(response, "Did you forget to register or load this tag?") def test_template_rendering(self): - request_url = self.page.get_absolute_url(self.language) + "?toolbar_off=true" + request_url = self.page.get_absolute_url() template = "snippet.html" + snippet_grouper = SnippetGrouper.objects.create() snippet = Snippet.objects.create( name="plugin_snippet", template=template, @@ -84,7 +100,7 @@ def test_template_rendering(self): self.pagecontent.placeholders.get(slot="content"), "SnippetPlugin", self.language, - snippet=snippet, + snippet_grouper=snippet_grouper, ) self.assertEqual(plugin.snippet.name, "plugin_snippet") self.assertEqual(plugin.snippet.slug, "plugin_snippet") @@ -100,20 +116,22 @@ def test_template_rendering(self): def test_failing_template_rendering(self): request_url = self.page.get_absolute_url(self.language) + "?toolbar_off=true" template = "some_template" + snippet_grouper = SnippetGrouper.objects.create() snippet = Snippet.objects.create( name="plugin_snippet", template=template, slug="plugin_snippet", + snippet_grouper=snippet_grouper, ) snippet.save() add_plugin( self.pagecontent.placeholders.get(slot="content"), "SnippetPlugin", self.language, - snippet=snippet, + snippet_grouper=snippet_grouper, ) with self.login_user_context(self.superuser): - response = self.client.get(request_url) + response = self.client.get(self.page.get_absolute_url()) self.assertContains(response, "Template some_template does not exist") From aa62ceddd28098d5bc52b46540a7345705848c22 Mon Sep 17 00:00:00 2001 From: Adam Murray Date: Fri, 10 Sep 2021 15:33:54 +0100 Subject: [PATCH 056/107] Plugin tests now use factories --- tests/test_plugins.py | 35 ++++++++++++----------------------- tests/utils/factories.py | 2 ++ 2 files changed, 14 insertions(+), 23 deletions(-) diff --git a/tests/test_plugins.py b/tests/test_plugins.py index 5382daf5..22a5f831 100644 --- a/tests/test_plugins.py +++ b/tests/test_plugins.py @@ -1,18 +1,12 @@ from cms.api import add_plugin, create_page -from cms.models import PageContent from cms.test_utils.testcases import CMSTestCase -from djangocms_snippet.models import Snippet, SnippetGrouper - - from .utils.factories import ( PageContentWithVersionFactory, - SnippetPluginFactory, SnippetWithVersionFactory, ) - class SnippetPluginsTestCase(CMSTestCase): def setUp(self): @@ -23,7 +17,6 @@ def setUp(self): "template": "page.html", "language": self.language, } - self.home_pagecontent = PageContentWithVersionFactory(**page_data) self.home = self.home_pagecontent.page page_data["title"] = "help" @@ -36,17 +29,13 @@ def setUp(self): def test_html_rendering(self): request_url = self.page.get_absolute_url(self.language) + "?toolbar_off=true" - snippet = SnippetWithVersionFactory( name="plugin_snippet", html="

Hello World

", slug="plugin_snippet", ) snippet_grouper = snippet.snippet_grouper - # SnippetPluginFactory(snippet_grouper=snippet_grouper, language=["en"]) - snippet.versions.last().publish(user=self.get_superuser()) - plugin = add_plugin( self.pagecontent.placeholders.get(slot="content"), "SnippetPlugin", @@ -65,14 +54,14 @@ def test_html_rendering(self): def test_failing_html_rendering(self): request_url = self.page.get_absolute_url(self.language) + "?toolbar_off=true" - snippet_grouper = SnippetGrouper.objects.create() - - Snippet.objects.create( + snippet = SnippetWithVersionFactory( name="plugin_snippet", html="{% import weirdness %}", slug="plugin_snippet", - snippet_grouper=snippet_grouper ) + snippet_grouper = snippet.snippet_grouper + snippet.versions.last().publish(user=self.get_superuser()) + add_plugin( self.pagecontent.placeholders.get(slot="content"), "SnippetPlugin", @@ -89,19 +78,20 @@ def test_failing_html_rendering(self): def test_template_rendering(self): request_url = self.page.get_absolute_url() template = "snippet.html" - snippet_grouper = SnippetGrouper.objects.create() - snippet = Snippet.objects.create( + snippet = SnippetWithVersionFactory( name="plugin_snippet", template=template, slug="plugin_snippet", ) - snippet.save() + snippet_grouper = snippet.snippet_grouper + snippet.versions.last().publish(user=self.get_superuser()) plugin = add_plugin( self.pagecontent.placeholders.get(slot="content"), "SnippetPlugin", self.language, snippet_grouper=snippet_grouper, ) + self.assertEqual(plugin.snippet.name, "plugin_snippet") self.assertEqual(plugin.snippet.slug, "plugin_snippet") @@ -116,14 +106,13 @@ def test_template_rendering(self): def test_failing_template_rendering(self): request_url = self.page.get_absolute_url(self.language) + "?toolbar_off=true" template = "some_template" - snippet_grouper = SnippetGrouper.objects.create() - snippet = Snippet.objects.create( + snippet = SnippetWithVersionFactory( name="plugin_snippet", template=template, slug="plugin_snippet", - snippet_grouper=snippet_grouper, ) - snippet.save() + snippet_grouper = snippet.snippet_grouper + snippet.versions.last().publish(user=self.get_superuser()) add_plugin( self.pagecontent.placeholders.get(slot="content"), "SnippetPlugin", @@ -132,6 +121,6 @@ def test_failing_template_rendering(self): ) with self.login_user_context(self.superuser): - response = self.client.get(self.page.get_absolute_url()) + response = self.client.get(request_url) self.assertContains(response, "Template some_template does not exist") diff --git a/tests/utils/factories.py b/tests/utils/factories.py index 5e993505..45089655 100644 --- a/tests/utils/factories.py +++ b/tests/utils/factories.py @@ -129,6 +129,8 @@ class AbstractSnippetFactory(factory.django.DjangoModelFactory): name = FuzzyText(length=12) slug = FuzzyText(length=12) snippet_grouper = factory.SubFactory(SnippetGrouperFactory) + html = "" + template = "" class Meta: abstract = True From 9fba5722a6b2e60e9484e1475d9f157289773985 Mon Sep 17 00:00:00 2001 From: Adam Murray Date: Fri, 10 Sep 2021 16:45:46 +0100 Subject: [PATCH 057/107] Linting --- .../migrations/0009_auto_20210909_0901.py | 3 +-- .../migrations/0012_auto_20210909_0912.py | 2 +- tests/test_models.py | 5 +---- tests/test_plugins.py | 5 ++--- tests/utils/factories.py | 11 +++-------- tests/utils/utils.py | 3 ++- 6 files changed, 10 insertions(+), 19 deletions(-) diff --git a/djangocms_snippet/migrations/0009_auto_20210909_0901.py b/djangocms_snippet/migrations/0009_auto_20210909_0901.py index 28e717d7..6bafc3b8 100644 --- a/djangocms_snippet/migrations/0009_auto_20210909_0901.py +++ b/djangocms_snippet/migrations/0009_auto_20210909_0901.py @@ -1,7 +1,6 @@ # Generated by Django 2.2.24 on 2021-09-09 09:01 - -from django.db import migrations, models import django.db.models.deletion +from django.db import migrations, models class Migration(migrations.Migration): diff --git a/djangocms_snippet/migrations/0012_auto_20210909_0912.py b/djangocms_snippet/migrations/0012_auto_20210909_0912.py index 5f8a8cd6..20b4dfa1 100644 --- a/djangocms_snippet/migrations/0012_auto_20210909_0912.py +++ b/djangocms_snippet/migrations/0012_auto_20210909_0912.py @@ -1,7 +1,7 @@ # Generated by Django 2.2.24 on 2021-09-09 09:12 -from django.db import migrations, models import django.db.models.deletion +from django.db import migrations, models class Migration(migrations.Migration): diff --git a/tests/test_models.py b/tests/test_models.py index c1e2b039..fd3cdec6 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -2,10 +2,7 @@ from djangocms_snippet.models import SEARCH_ENABLED, Snippet, SnippetPtr -from .utils.factories import ( - SnippetPluginFactory, - SnippetWithVersionFactory, -) +from .utils.factories import SnippetPluginFactory, SnippetWithVersionFactory class SnippetModelTestCase(CMSTestCase): diff --git a/tests/test_plugins.py b/tests/test_plugins.py index 22a5f831..3664655d 100644 --- a/tests/test_plugins.py +++ b/tests/test_plugins.py @@ -1,9 +1,8 @@ -from cms.api import add_plugin, create_page +from cms.api import add_plugin from cms.test_utils.testcases import CMSTestCase from .utils.factories import ( - PageContentWithVersionFactory, - SnippetWithVersionFactory, + PageContentWithVersionFactory, SnippetWithVersionFactory, ) diff --git a/tests/utils/factories.py b/tests/utils/factories.py index 45089655..98026741 100644 --- a/tests/utils/factories.py +++ b/tests/utils/factories.py @@ -5,18 +5,13 @@ from django.contrib.sites.models import Site from cms import constants -from cms.models import Page, PageContent, PageUrl, Placeholder, TreeNode +from cms.models import Page, PageContent, Placeholder, TreeNode import factory -from factory.fuzzy import FuzzyChoice, FuzzyInteger, FuzzyText - from djangocms_versioning.models import Version +from factory.fuzzy import FuzzyChoice, FuzzyInteger, FuzzyText -from djangocms_snippet.models import ( - Snippet, - SnippetGrouper, - SnippetPtr -) +from djangocms_snippet.models import Snippet, SnippetGrouper, SnippetPtr class PlaceholderFactory(factory.django.DjangoModelFactory): diff --git a/tests/utils/utils.py b/tests/utils/utils.py index 1dabc21c..22c38d43 100644 --- a/tests/utils/utils.py +++ b/tests/utils/utils.py @@ -1,7 +1,8 @@ from djangocms_snippet.cms_config import SnippetCMSAppConfig + try: - from djangocms_versioning import __version__ + from djangocms_versioning import __version__ # NOQA versioning_installed = True except ImportError: versioning_installed = False From aeaa52a54385ac171fa76a5716c8d4493f7c6f1c Mon Sep 17 00:00:00 2001 From: Adam Murray Date: Fri, 10 Sep 2021 16:47:05 +0100 Subject: [PATCH 058/107] Linting --- tests/utils/__init__.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/utils/__init__.py b/tests/utils/__init__.py index 8b137891..e69de29b 100644 --- a/tests/utils/__init__.py +++ b/tests/utils/__init__.py @@ -1 +0,0 @@ - From bdf4eaa26265b08d7a0a62f79020e80f4c9e8cbe Mon Sep 17 00:00:00 2001 From: Adam Murray Date: Mon, 13 Sep 2021 11:38:10 +0100 Subject: [PATCH 059/107] Fixed old issue with migrations --- .../migrations/0010_cms4_grouper_version_data_migration.py | 2 +- djangocms_snippet/migrations/0011_cms4_plugin_data_migration.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/djangocms_snippet/migrations/0010_cms4_grouper_version_data_migration.py b/djangocms_snippet/migrations/0010_cms4_grouper_version_data_migration.py index 619ae8d2..c77562de 100644 --- a/djangocms_snippet/migrations/0010_cms4_grouper_version_data_migration.py +++ b/djangocms_snippet/migrations/0010_cms4_grouper_version_data_migration.py @@ -32,7 +32,7 @@ def cms4_grouper_version_migration(apps, schema_editor): for snippet in snippet_queryset: grouper = SnippetGrouper.objects.create() - snippet.new_snippet = grouper + snippet.snipept_grouper = grouper snippet.save() # Get a migration user. diff --git a/djangocms_snippet/migrations/0011_cms4_plugin_data_migration.py b/djangocms_snippet/migrations/0011_cms4_plugin_data_migration.py index 632559f1..a290c198 100644 --- a/djangocms_snippet/migrations/0011_cms4_plugin_data_migration.py +++ b/djangocms_snippet/migrations/0011_cms4_plugin_data_migration.py @@ -8,7 +8,7 @@ def cms4_migration(apps, schema_editor): for snippet_plugin in SnippetPtr.objects.all(): snippet = snippet_plugin.snippet grouper = snippet.snippet_grouper - snippet_plugin.new_snippet = grouper + snippet_plugin.snipept_grouper = grouper snippet_plugin.save() From aa5a54c918532e66f947dc14216fd8f691c75384 Mon Sep 17 00:00:00 2001 From: Adam Murray Date: Mon, 13 Sep 2021 11:38:37 +0100 Subject: [PATCH 060/107] Fixed old issue with migrations --- .../migrations/0010_cms4_grouper_version_data_migration.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/djangocms_snippet/migrations/0010_cms4_grouper_version_data_migration.py b/djangocms_snippet/migrations/0010_cms4_grouper_version_data_migration.py index c77562de..c10fedef 100644 --- a/djangocms_snippet/migrations/0010_cms4_grouper_version_data_migration.py +++ b/djangocms_snippet/migrations/0010_cms4_grouper_version_data_migration.py @@ -32,7 +32,7 @@ def cms4_grouper_version_migration(apps, schema_editor): for snippet in snippet_queryset: grouper = SnippetGrouper.objects.create() - snippet.snipept_grouper = grouper + snippet.snippet_grouper = grouper snippet.save() # Get a migration user. From 2d36a3b9e646b5e360d529fc53e52d0866da7e73 Mon Sep 17 00:00:00 2001 From: Adam Murray Date: Mon, 13 Sep 2021 11:42:59 +0100 Subject: [PATCH 061/107] Fixed spelling mistake --- djangocms_snippet/migrations/0011_cms4_plugin_data_migration.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/djangocms_snippet/migrations/0011_cms4_plugin_data_migration.py b/djangocms_snippet/migrations/0011_cms4_plugin_data_migration.py index a290c198..534d0490 100644 --- a/djangocms_snippet/migrations/0011_cms4_plugin_data_migration.py +++ b/djangocms_snippet/migrations/0011_cms4_plugin_data_migration.py @@ -8,7 +8,7 @@ def cms4_migration(apps, schema_editor): for snippet_plugin in SnippetPtr.objects.all(): snippet = snippet_plugin.snippet grouper = snippet.snippet_grouper - snippet_plugin.snipept_grouper = grouper + snippet_plugin.snippet_grouper = grouper snippet_plugin.save() From a8f56f3acc1defa5638204b84d4fe4726dd0baaf Mon Sep 17 00:00:00 2001 From: Adam Murray Date: Mon, 13 Sep 2021 17:37:03 +0100 Subject: [PATCH 062/107] Updated test to no longer use factoris --- tests/test_plugins.py | 35 ++++++++++++++++++++--------------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/tests/test_plugins.py b/tests/test_plugins.py index 3664655d..f4147b22 100644 --- a/tests/test_plugins.py +++ b/tests/test_plugins.py @@ -1,8 +1,8 @@ -from cms.api import add_plugin +from cms.api import add_plugin, create_page, create_title from cms.test_utils.testcases import CMSTestCase from .utils.factories import ( - PageContentWithVersionFactory, SnippetWithVersionFactory, + SnippetWithVersionFactory, ) @@ -12,29 +12,29 @@ def setUp(self): self.language = "en" self.superuser = self.get_superuser() page_data = { - "title": "home", - "template": "page.html", - "language": self.language, + "title": "home", "template": "page.html", "language": self.language, + "created_by": self.superuser, "published": True, } - self.home_pagecontent = PageContentWithVersionFactory(**page_data) - self.home = self.home_pagecontent.page - page_data["title"] = "help" - self.pagecontent = PageContentWithVersionFactory(**page_data) - self.page = self.pagecontent.page - self.pagecontent.versions.first().publish(user=self.superuser) - self.page.save() + self.home = create_page(**page_data) + + title_data = { + "title": "home", "template": "page.html", "language": self.language, + "created_by": self.superuser, "page": self.home, + } + self.home_pagecontent = create_title(**title_data) - self.placeholder = self.pagecontent.placeholders.create(slot="content") + page_data["title"] = "help" + self.page = create_page(**page_data) + title_data["page"] = self.page + self.pagecontent = create_title(**title_data) def test_html_rendering(self): - request_url = self.page.get_absolute_url(self.language) + "?toolbar_off=true" snippet = SnippetWithVersionFactory( name="plugin_snippet", html="

Hello World

", slug="plugin_snippet", ) snippet_grouper = snippet.snippet_grouper - snippet.versions.last().publish(user=self.get_superuser()) plugin = add_plugin( self.pagecontent.placeholders.get(slot="content"), "SnippetPlugin", @@ -42,6 +42,9 @@ def test_html_rendering(self): snippet_grouper=snippet_grouper, ) + snippet.versions.last().publish(user=self.get_superuser()) + request_url = self.page.get_absolute_url("en") + self.assertEqual(plugin.snippet.name, "plugin_snippet") self.assertEqual(plugin.snippet.html, "

Hello World

") self.assertEqual(plugin.snippet.slug, "plugin_snippet") @@ -49,6 +52,8 @@ def test_html_rendering(self): with self.login_user_context(self.superuser): response = self.client.get(request_url) + import pdb + pdb.set_trace() self.assertIn(b"

Hello World

", response.content) def test_failing_html_rendering(self): From b87a0d69e09e6fad3e109217c685efcee4fa41b1 Mon Sep 17 00:00:00 2001 From: Adam Murray Date: Mon, 13 Sep 2021 17:46:13 +0100 Subject: [PATCH 063/107] Fixed rendering --- tests/test_plugins.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/test_plugins.py b/tests/test_plugins.py index f4147b22..92dbff5f 100644 --- a/tests/test_plugins.py +++ b/tests/test_plugins.py @@ -28,6 +28,10 @@ def setUp(self): title_data["page"] = self.page self.pagecontent = create_title(**title_data) + # Publish our page content + self.home_pagecontent.versions.last().publish(user=self.superuser) + self.pagecontent.versions.last().publish(user=self.superuser) + def test_html_rendering(self): snippet = SnippetWithVersionFactory( name="plugin_snippet", @@ -52,8 +56,6 @@ def test_html_rendering(self): with self.login_user_context(self.superuser): response = self.client.get(request_url) - import pdb - pdb.set_trace() self.assertIn(b"

Hello World

", response.content) def test_failing_html_rendering(self): From 7375e5b3cf51bd145a55864f71cb6d9f4b7e9cbe Mon Sep 17 00:00:00 2001 From: Adam Murray Date: Mon, 13 Sep 2021 21:43:49 +0100 Subject: [PATCH 064/107] Fixed migration error --- djangocms_snippet/migrations/0009_auto_20210909_0901.py | 3 ++- .../migrations/0011_cms4_plugin_data_migration.py | 3 +-- djangocms_snippet/migrations/0012_auto_20210909_0912.py | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/djangocms_snippet/migrations/0009_auto_20210909_0901.py b/djangocms_snippet/migrations/0009_auto_20210909_0901.py index 6bafc3b8..28e717d7 100644 --- a/djangocms_snippet/migrations/0009_auto_20210909_0901.py +++ b/djangocms_snippet/migrations/0009_auto_20210909_0901.py @@ -1,6 +1,7 @@ # Generated by Django 2.2.24 on 2021-09-09 09:01 -import django.db.models.deletion + from django.db import migrations, models +import django.db.models.deletion class Migration(migrations.Migration): diff --git a/djangocms_snippet/migrations/0011_cms4_plugin_data_migration.py b/djangocms_snippet/migrations/0011_cms4_plugin_data_migration.py index 534d0490..449236d8 100644 --- a/djangocms_snippet/migrations/0011_cms4_plugin_data_migration.py +++ b/djangocms_snippet/migrations/0011_cms4_plugin_data_migration.py @@ -7,8 +7,7 @@ def cms4_migration(apps, schema_editor): for snippet_plugin in SnippetPtr.objects.all(): snippet = snippet_plugin.snippet - grouper = snippet.snippet_grouper - snippet_plugin.snippet_grouper = grouper + snippet_plugin.snippet_grouper = snippet.snippet_grouper snippet_plugin.save() diff --git a/djangocms_snippet/migrations/0012_auto_20210909_0912.py b/djangocms_snippet/migrations/0012_auto_20210909_0912.py index 20b4dfa1..5f8a8cd6 100644 --- a/djangocms_snippet/migrations/0012_auto_20210909_0912.py +++ b/djangocms_snippet/migrations/0012_auto_20210909_0912.py @@ -1,7 +1,7 @@ # Generated by Django 2.2.24 on 2021-09-09 09:12 -import django.db.models.deletion from django.db import migrations, models +import django.db.models.deletion class Migration(migrations.Migration): From 03df8f7237d9ab680f20194278546d0397233778 Mon Sep 17 00:00:00 2001 From: Adam Murray Date: Mon, 13 Sep 2021 21:51:09 +0100 Subject: [PATCH 065/107] Updated comments --- .../migrations/0010_cms4_grouper_version_data_migration.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/djangocms_snippet/migrations/0010_cms4_grouper_version_data_migration.py b/djangocms_snippet/migrations/0010_cms4_grouper_version_data_migration.py index c10fedef..4a20b171 100644 --- a/djangocms_snippet/migrations/0010_cms4_grouper_version_data_migration.py +++ b/djangocms_snippet/migrations/0010_cms4_grouper_version_data_migration.py @@ -17,7 +17,6 @@ def cms4_grouper_version_migration(apps, schema_editor): - # TODO: Remove create_contenttypes(global_apps.get_app_config("djangocms_snippet")) djangocms_versioning_config_enabled = SnippetCMSAppConfig.djangocms_versioning_enabled @@ -38,6 +37,7 @@ def cms4_grouper_version_migration(apps, schema_editor): # Get a migration user. migration_user = User.objects.get(id=DJANGOCMS_SNIPPET_VERSIONING_MIGRATION_USER_ID) + # Create initial Snippet Versions if versioning is enabled and installed. if djangocms_versioning_config_enabled and djangocms_versioning_installed: Version = apps.get_model('djangocms_versioning', 'Version') Version.objects.create( From f895bf185fb63da806947d84cf0087772121caf1 Mon Sep 17 00:00:00 2001 From: Adam Murray Date: Tue, 14 Sep 2021 08:43:21 +0100 Subject: [PATCH 066/107] Migration linting --- djangocms_snippet/migrations/0009_auto_20210909_0901.py | 2 +- djangocms_snippet/migrations/0012_auto_20210909_0912.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/djangocms_snippet/migrations/0009_auto_20210909_0901.py b/djangocms_snippet/migrations/0009_auto_20210909_0901.py index 28e717d7..8d804482 100644 --- a/djangocms_snippet/migrations/0009_auto_20210909_0901.py +++ b/djangocms_snippet/migrations/0009_auto_20210909_0901.py @@ -1,7 +1,7 @@ # Generated by Django 2.2.24 on 2021-09-09 09:01 -from django.db import migrations, models import django.db.models.deletion +from django.db import migrations, models class Migration(migrations.Migration): diff --git a/djangocms_snippet/migrations/0012_auto_20210909_0912.py b/djangocms_snippet/migrations/0012_auto_20210909_0912.py index 5f8a8cd6..20b4dfa1 100644 --- a/djangocms_snippet/migrations/0012_auto_20210909_0912.py +++ b/djangocms_snippet/migrations/0012_auto_20210909_0912.py @@ -1,7 +1,7 @@ # Generated by Django 2.2.24 on 2021-09-09 09:12 -from django.db import migrations, models import django.db.models.deletion +from django.db import migrations, models class Migration(migrations.Migration): From e4cf009ad76c045a86a5a35a878c3d959249d8e7 Mon Sep 17 00:00:00 2001 From: Adam Murray Date: Tue, 14 Sep 2021 15:47:04 +0100 Subject: [PATCH 067/107] Made copy function test and started copy function --- djangocms_snippet/cms_config.py | 16 ++++++++++++++++ djangocms_snippet/models.py | 1 - tests/test_config.py | 22 ++++++++++++++++++++++ 3 files changed, 38 insertions(+), 1 deletion(-) create mode 100644 tests/test_config.py diff --git a/djangocms_snippet/cms_config.py b/djangocms_snippet/cms_config.py index cf87874d..53b055f9 100644 --- a/djangocms_snippet/cms_config.py +++ b/djangocms_snippet/cms_config.py @@ -5,6 +5,22 @@ from .models import Snippet +def _get_model_fields(instance, model, field_exclusion_list=[]): + field_exclusion_list.append(model._meta.pk.name) + return { + field.name: getattr(instance, field.name) + for field in model._meta.fields + if field.name not in field_exclusion_list + } + + +def snippet_copy_method(old_snippet): + old_snippet_fields = _get_model_fields(old_snippet, Snippet) + import pdb + pdb.set_trace() + new_snippet = Snippet.objects.create(**old_snippet_fields) + + class SnippetCMSAppConfig(CMSAppConfig): djangocms_versioning_enabled = getattr( settings, 'DJANGOCMS_SNIPPET_VERSIONING_ENABLED', False diff --git a/djangocms_snippet/models.py b/djangocms_snippet/models.py index bf7703a9..aa057f78 100644 --- a/djangocms_snippet/models.py +++ b/djangocms_snippet/models.py @@ -45,7 +45,6 @@ class Snippet(models.Model): ) slug = models.SlugField( verbose_name=_('Slug'), - unique=True, blank=False, default='', max_length=255, diff --git a/tests/test_config.py b/tests/test_config.py new file mode 100644 index 00000000..fb822f59 --- /dev/null +++ b/tests/test_config.py @@ -0,0 +1,22 @@ +from cms.test_utils.testcases import CMSTestCase + +from djangocms_snippet.cms_config import snippet_copy_method + +from .utils.factories import SnippetWithVersionFactory + + +class VersioningConfigTestCase(CMSTestCase): + + def test_snippet_copy_method(self): + old_snippet = SnippetWithVersionFactory( + name="snippet", + html="

Hello World

", + slug="snippet", + ) + + new_snippet = snippet_copy_method(old_snippet) + + self.assertEqual(old_snippet.name, new_snippet.name) + self.assertEqual(old_snippet.html, new_snippet.html) + self.assertEqual(old_snippet.snippet_grouper, new_snippet.snippet_grouper) + self.assertEqual(old_snippet.versions.count() + 1, new_snippet.versions.count()) From 79eebf4df42525ceab4d67d5e7c558e2b0954d99 Mon Sep 17 00:00:00 2001 From: Adam Murray Date: Tue, 14 Sep 2021 16:30:46 +0100 Subject: [PATCH 068/107] Remove unique=True from snipept slug field --- djangocms_snippet/migrations/0009_auto_20210909_0901.py | 5 +++++ djangocms_snippet/models.py | 1 - 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/djangocms_snippet/migrations/0009_auto_20210909_0901.py b/djangocms_snippet/migrations/0009_auto_20210909_0901.py index 8d804482..0e2e8f79 100644 --- a/djangocms_snippet/migrations/0009_auto_20210909_0901.py +++ b/djangocms_snippet/migrations/0009_auto_20210909_0901.py @@ -17,6 +17,11 @@ class Migration(migrations.Migration): ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ], ), + migrations.AlterField( + model_name='snippet', + name='slug', + field=models.SlugField(default='', max_length=255, verbose_name='Slug'), + ), migrations.AddField( model_name='snippet', name='snippet_grouper', diff --git a/djangocms_snippet/models.py b/djangocms_snippet/models.py index bf7703a9..aa057f78 100644 --- a/djangocms_snippet/models.py +++ b/djangocms_snippet/models.py @@ -45,7 +45,6 @@ class Snippet(models.Model): ) slug = models.SlugField( verbose_name=_('Slug'), - unique=True, blank=False, default='', max_length=255, From 38c211d071d1b766da73103511ac954eaec12fa6 Mon Sep 17 00:00:00 2001 From: Adam Murray Date: Tue, 14 Sep 2021 16:50:19 +0100 Subject: [PATCH 069/107] Removed unique=True on name --- djangocms_snippet/migrations/0009_auto_20210909_0901.py | 5 +++++ djangocms_snippet/models.py | 1 - 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/djangocms_snippet/migrations/0009_auto_20210909_0901.py b/djangocms_snippet/migrations/0009_auto_20210909_0901.py index 0e2e8f79..58fcdd20 100644 --- a/djangocms_snippet/migrations/0009_auto_20210909_0901.py +++ b/djangocms_snippet/migrations/0009_auto_20210909_0901.py @@ -17,6 +17,11 @@ class Migration(migrations.Migration): ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ], ), + migrations.AlterField( + model_name='snippet', + name='name', + field=models.CharField(max_length=255, verbose_name='Name'), + ), migrations.AlterField( model_name='snippet', name='slug', diff --git a/djangocms_snippet/models.py b/djangocms_snippet/models.py index aa057f78..700a07dc 100644 --- a/djangocms_snippet/models.py +++ b/djangocms_snippet/models.py @@ -20,7 +20,6 @@ class Snippet(models.Model): """ name = models.CharField( verbose_name=_('Name'), - unique=True, max_length=255, ) snippet_grouper = models.ForeignKey( From 0cd495ba23b815038e3094bb322daa82970485c7 Mon Sep 17 00:00:00 2001 From: Adam Murray Date: Tue, 14 Sep 2021 17:21:58 +0100 Subject: [PATCH 070/107] Enabled moderation, updates to cms_config --- djangocms_snippet/cms_config.py | 25 ++++++++++++++----- .../migrations/0009_auto_20210909_0901.py | 5 ++++ djangocms_snippet/models.py | 1 - tests/test_config.py | 6 ++++- 4 files changed, 29 insertions(+), 8 deletions(-) diff --git a/djangocms_snippet/cms_config.py b/djangocms_snippet/cms_config.py index 53b055f9..da802c85 100644 --- a/djangocms_snippet/cms_config.py +++ b/djangocms_snippet/cms_config.py @@ -6,6 +6,13 @@ def _get_model_fields(instance, model, field_exclusion_list=[]): + """ + Iterate over fields excluding + :param instance: + :param model: + :param field_exclusion_list: + :return: + """ field_exclusion_list.append(model._meta.pk.name) return { field.name: getattr(instance, field.name) @@ -15,10 +22,12 @@ def _get_model_fields(instance, model, field_exclusion_list=[]): def snippet_copy_method(old_snippet): - old_snippet_fields = _get_model_fields(old_snippet, Snippet) - import pdb - pdb.set_trace() - new_snippet = Snippet.objects.create(**old_snippet_fields) + """ + The most basic copy method, given the model only contains simple foreign key relationships + :param old_snippet: Old Snippet instance + :return: New Snippet instance with old instance values (excluding ID) + """ + return Snippet.objects.create(**_get_model_fields(old_snippet, Snippet)) class SnippetCMSAppConfig(CMSAppConfig): @@ -26,15 +35,19 @@ class SnippetCMSAppConfig(CMSAppConfig): settings, 'DJANGOCMS_SNIPPET_VERSIONING_ENABLED', False ) + # TODO: Update this to check if moderation is installed and enabled + djangocms_moderation_enabled = True + moderated_models = [] + if djangocms_versioning_enabled: from djangocms_versioning.datastructures import ( - VersionableItem, default_copy, + VersionableItem, ) versioning = [ VersionableItem( content_model=Snippet, grouper_field_name="snippet_grouper", - copy_function=default_copy, + copy_function=snippet_copy_method, ) ] diff --git a/djangocms_snippet/migrations/0009_auto_20210909_0901.py b/djangocms_snippet/migrations/0009_auto_20210909_0901.py index 0e2e8f79..58fcdd20 100644 --- a/djangocms_snippet/migrations/0009_auto_20210909_0901.py +++ b/djangocms_snippet/migrations/0009_auto_20210909_0901.py @@ -17,6 +17,11 @@ class Migration(migrations.Migration): ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ], ), + migrations.AlterField( + model_name='snippet', + name='name', + field=models.CharField(max_length=255, verbose_name='Name'), + ), migrations.AlterField( model_name='snippet', name='slug', diff --git a/djangocms_snippet/models.py b/djangocms_snippet/models.py index aa057f78..700a07dc 100644 --- a/djangocms_snippet/models.py +++ b/djangocms_snippet/models.py @@ -20,7 +20,6 @@ class Snippet(models.Model): """ name = models.CharField( verbose_name=_('Name'), - unique=True, max_length=255, ) snippet_grouper = models.ForeignKey( diff --git a/tests/test_config.py b/tests/test_config.py index fb822f59..46423e40 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -13,10 +13,14 @@ def test_snippet_copy_method(self): html="

Hello World

", slug="snippet", ) + version_count = old_snippet.versions.count() new_snippet = snippet_copy_method(old_snippet) + import pdb + pdb.set_trace() + self.assertEqual(old_snippet.name, new_snippet.name) self.assertEqual(old_snippet.html, new_snippet.html) self.assertEqual(old_snippet.snippet_grouper, new_snippet.snippet_grouper) - self.assertEqual(old_snippet.versions.count() + 1, new_snippet.versions.count()) + self.assertEqual(version_count + 1, new_snippet.versions.count()) From 247ae360c7cce23b857477b5612f20223daa0205 Mon Sep 17 00:00:00 2001 From: Adam Murray Date: Tue, 14 Sep 2021 18:06:21 +0100 Subject: [PATCH 071/107] Updated config test --- tests/test_config.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/tests/test_config.py b/tests/test_config.py index 46423e40..10821277 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -13,14 +13,9 @@ def test_snippet_copy_method(self): html="

Hello World

", slug="snippet", ) - version_count = old_snippet.versions.count() new_snippet = snippet_copy_method(old_snippet) - import pdb - pdb.set_trace() - self.assertEqual(old_snippet.name, new_snippet.name) self.assertEqual(old_snippet.html, new_snippet.html) self.assertEqual(old_snippet.snippet_grouper, new_snippet.snippet_grouper) - self.assertEqual(version_count + 1, new_snippet.versions.count()) From ee07ad5203b8d49273898f7b417fbad8f6cb0b8f Mon Sep 17 00:00:00 2001 From: Adam Murray Date: Wed, 15 Sep 2021 08:46:09 +0100 Subject: [PATCH 072/107] Update djangocms_snippet/models.py Co-authored-by: Aiky30 --- djangocms_snippet/models.py | 1 - 1 file changed, 1 deletion(-) diff --git a/djangocms_snippet/models.py b/djangocms_snippet/models.py index 700a07dc..1b5bd38a 100644 --- a/djangocms_snippet/models.py +++ b/djangocms_snippet/models.py @@ -70,7 +70,6 @@ class SnippetPtr(CMSPlugin): parent_link=True, on_delete=models.CASCADE, ) - snippet_grouper = models.ForeignKey(SnippetGrouper, on_delete=models.CASCADE) search_fields = ['snippet__html'] if SEARCH_ENABLED else [] From 9b23fa857f6b91523eb62f6e75809e45e9aae3cd Mon Sep 17 00:00:00 2001 From: Adam Murray Date: Wed, 15 Sep 2021 11:08:36 +0100 Subject: [PATCH 073/107] Refactrogin --- ...909_0901.py => 0009_auto_20210915_0445.py} | 14 +--- ...010_cms4_grouper_version_data_migration.py | 2 +- .../migrations/0012_auto_20210909_0912.py | 23 ------ .../0012_remove_snippetptr_snippet.py | 17 +++++ djangocms_snippet/models.py | 9 ++- tests/test_plugins.py | 16 ++-- tests/utils/factories.py | 75 ++----------------- 7 files changed, 43 insertions(+), 113 deletions(-) rename djangocms_snippet/migrations/{0009_auto_20210909_0901.py => 0009_auto_20210915_0445.py} (70%) delete mode 100644 djangocms_snippet/migrations/0012_auto_20210909_0912.py create mode 100644 djangocms_snippet/migrations/0012_remove_snippetptr_snippet.py diff --git a/djangocms_snippet/migrations/0009_auto_20210909_0901.py b/djangocms_snippet/migrations/0009_auto_20210915_0445.py similarity index 70% rename from djangocms_snippet/migrations/0009_auto_20210909_0901.py rename to djangocms_snippet/migrations/0009_auto_20210915_0445.py index 58fcdd20..2dbc5912 100644 --- a/djangocms_snippet/migrations/0009_auto_20210909_0901.py +++ b/djangocms_snippet/migrations/0009_auto_20210915_0445.py @@ -1,7 +1,7 @@ -# Generated by Django 2.2.24 on 2021-09-09 09:01 +# Generated by Django 2.2.24 on 2021-09-15 04:45 -import django.db.models.deletion from django.db import migrations, models +import django.db.models.deletion class Migration(migrations.Migration): @@ -17,16 +17,6 @@ class Migration(migrations.Migration): ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ], ), - migrations.AlterField( - model_name='snippet', - name='name', - field=models.CharField(max_length=255, verbose_name='Name'), - ), - migrations.AlterField( - model_name='snippet', - name='slug', - field=models.SlugField(default='', max_length=255, verbose_name='Slug'), - ), migrations.AddField( model_name='snippet', name='snippet_grouper', diff --git a/djangocms_snippet/migrations/0010_cms4_grouper_version_data_migration.py b/djangocms_snippet/migrations/0010_cms4_grouper_version_data_migration.py index 4a20b171..dee1d352 100644 --- a/djangocms_snippet/migrations/0010_cms4_grouper_version_data_migration.py +++ b/djangocms_snippet/migrations/0010_cms4_grouper_version_data_migration.py @@ -52,7 +52,7 @@ def cms4_grouper_version_migration(apps, schema_editor): class Migration(migrations.Migration): dependencies = [ ('cms', '0034_remove_pagecontent_placeholders'), # Run after the CMS4 migrations - ('djangocms_snippet', '0009_auto_20210909_0901'), + ('djangocms_snippet', '0009_auto_20210915_0445'), ] if djangocms_versioning_installed: diff --git a/djangocms_snippet/migrations/0012_auto_20210909_0912.py b/djangocms_snippet/migrations/0012_auto_20210909_0912.py deleted file mode 100644 index 20b4dfa1..00000000 --- a/djangocms_snippet/migrations/0012_auto_20210909_0912.py +++ /dev/null @@ -1,23 +0,0 @@ -# Generated by Django 2.2.24 on 2021-09-09 09:12 - -import django.db.models.deletion -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('djangocms_snippet', '0011_cms4_plugin_data_migration'), - ] - - operations = [ - migrations.RemoveField( - model_name='snippetptr', - name='snippet', - ), - migrations.AlterField( - model_name='snippetptr', - name='snippet_grouper', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='djangocms_snippet.SnippetGrouper'), - ), - ] diff --git a/djangocms_snippet/migrations/0012_remove_snippetptr_snippet.py b/djangocms_snippet/migrations/0012_remove_snippetptr_snippet.py new file mode 100644 index 00000000..8585fca6 --- /dev/null +++ b/djangocms_snippet/migrations/0012_remove_snippetptr_snippet.py @@ -0,0 +1,17 @@ +# Generated by Django 2.2.24 on 2021-09-15 05:06 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('djangocms_snippet', '0011_cms4_plugin_data_migration'), + ] + + operations = [ + migrations.RemoveField( + model_name='snippetptr', + name='snippet', + ), + ] diff --git a/djangocms_snippet/models.py b/djangocms_snippet/models.py index 700a07dc..2460d53d 100644 --- a/djangocms_snippet/models.py +++ b/djangocms_snippet/models.py @@ -21,6 +21,7 @@ class Snippet(models.Model): name = models.CharField( verbose_name=_('Name'), max_length=255, + unique=True, ) snippet_grouper = models.ForeignKey( SnippetGrouper, @@ -47,6 +48,7 @@ class Snippet(models.Model): blank=False, default='', max_length=255, + unique=True, ) def __str__(self): @@ -70,7 +72,12 @@ class SnippetPtr(CMSPlugin): parent_link=True, on_delete=models.CASCADE, ) - snippet_grouper = models.ForeignKey(SnippetGrouper, on_delete=models.CASCADE) + snippet_grouper = models.ForeignKey( + SnippetGrouper, + on_delete=models.CASCADE, + blank=True, + null=True, + ) search_fields = ['snippet__html'] if SEARCH_ENABLED else [] diff --git a/tests/test_plugins.py b/tests/test_plugins.py index 92dbff5f..1a5dd2c3 100644 --- a/tests/test_plugins.py +++ b/tests/test_plugins.py @@ -11,20 +11,20 @@ class SnippetPluginsTestCase(CMSTestCase): def setUp(self): self.language = "en" self.superuser = self.get_superuser() - page_data = { - "title": "home", "template": "page.html", "language": self.language, - "created_by": self.superuser, "published": True, - } - self.home = create_page(**page_data) + self.home = create_page( + title="home", template="page.html", + language=self.language, created_by=self.superuser, + ) title_data = { "title": "home", "template": "page.html", "language": self.language, "created_by": self.superuser, "page": self.home, } self.home_pagecontent = create_title(**title_data) - - page_data["title"] = "help" - self.page = create_page(**page_data) + self.page = create_page( + title="help", template="page.html", + language=self.language, created_by=self.superuser, + ) title_data["page"] = self.page self.pagecontent = create_title(**title_data) diff --git a/tests/utils/factories.py b/tests/utils/factories.py index 98026741..a601af7c 100644 --- a/tests/utils/factories.py +++ b/tests/utils/factories.py @@ -2,10 +2,8 @@ from django.contrib.auth.models import User from django.contrib.contenttypes.models import ContentType -from django.contrib.sites.models import Site -from cms import constants -from cms.models import Page, PageContent, Placeholder, TreeNode +from cms.models import Placeholder import factory from djangocms_versioning.models import Version @@ -14,16 +12,6 @@ from djangocms_snippet.models import Snippet, SnippetGrouper, SnippetPtr -class PlaceholderFactory(factory.django.DjangoModelFactory): - default_width = FuzzyInteger(0, 25) - slot = FuzzyText(length=2, chars=string.digits) - # NOTE: When using this factory you will probably want to set - # the source field manually - - class Meta: - model = Placeholder - - class UserFactory(factory.django.DjangoModelFactory): username = FuzzyText(length=12) first_name = factory.Faker("first_name") @@ -55,63 +43,14 @@ class Meta: abstract = True -class TreeNodeFactory(factory.django.DjangoModelFactory): - site = factory.fuzzy.FuzzyChoice(Site.objects.all()) - depth = 0 - # NOTE: Generating path this way is probably not a good way of - # doing it, but seems to work for our present tests which only - # really need a tree node to exist and not throw unique constraint - # errors on this field. If the data in this model starts mattering - # in our tests then something more will need to be done here. - path = FuzzyText(length=8, chars=string.digits) - - class Meta: - model = TreeNode - - -class PageFactory(factory.django.DjangoModelFactory): - node = factory.SubFactory(TreeNodeFactory) - - class Meta: - model = Page - - -class PageContentFactory(factory.django.DjangoModelFactory): - page = factory.SubFactory(PageFactory) - language = FuzzyChoice(["en", "fr", "it"]) - title = FuzzyText(length=12) - page_title = FuzzyText(length=12) - menu_title = FuzzyText(length=12) - meta_description = FuzzyText(length=12) - redirect = FuzzyText(length=12) - created_by = FuzzyText(length=12) - changed_by = FuzzyText(length=12) - in_navigation = FuzzyChoice([True, False]) - soft_root = FuzzyChoice([True, False]) - limit_visibility_in_menu = constants.VISIBILITY_USERS - template = 'page.html' - xframe_options = FuzzyInteger(0, 25) - - class Meta: - model = PageContent - - -class PageVersionFactory(AbstractVersionFactory): - content = factory.SubFactory(PageContentFactory) +class PlaceholderFactory(factory.django.DjangoModelFactory): + default_width = FuzzyInteger(0, 25) + slot = FuzzyText(length=2, chars=string.digits) + # NOTE: When using this factory you will probably want to set + # the source field manually class Meta: - model = Version - - -class PageContentWithVersionFactory(PageContentFactory): - @factory.post_generation - def version(self, create, extracted, **kwargs): - # NOTE: Use this method as below to define version attributes: - # PageContentWithVersionFactory(version__label='label1') - if not create: - # Simple build, do nothing. - return - PageVersionFactory(content=self, **kwargs) + model = Placeholder class SnippetGrouperFactory(factory.django.DjangoModelFactory): From 7cb6cc8da8ca945bff2069a0d35316f0fd225884 Mon Sep 17 00:00:00 2001 From: Adam Murray Date: Wed, 15 Sep 2021 11:11:31 +0100 Subject: [PATCH 074/107] Linting --- djangocms_snippet/migrations/0009_auto_20210915_0445.py | 2 +- tests/utils/factories.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/djangocms_snippet/migrations/0009_auto_20210915_0445.py b/djangocms_snippet/migrations/0009_auto_20210915_0445.py index 2dbc5912..ee7ffd67 100644 --- a/djangocms_snippet/migrations/0009_auto_20210915_0445.py +++ b/djangocms_snippet/migrations/0009_auto_20210915_0445.py @@ -1,7 +1,7 @@ # Generated by Django 2.2.24 on 2021-09-15 04:45 -from django.db import migrations, models import django.db.models.deletion +from django.db import migrations, models class Migration(migrations.Migration): diff --git a/tests/utils/factories.py b/tests/utils/factories.py index a601af7c..9d6210c6 100644 --- a/tests/utils/factories.py +++ b/tests/utils/factories.py @@ -7,7 +7,7 @@ import factory from djangocms_versioning.models import Version -from factory.fuzzy import FuzzyChoice, FuzzyInteger, FuzzyText +from factory.fuzzy import FuzzyInteger, FuzzyText from djangocms_snippet.models import Snippet, SnippetGrouper, SnippetPtr From b59a31d316d9e84e29d4ad1f76896e7231fef996 Mon Sep 17 00:00:00 2001 From: Adam Murray Date: Wed, 15 Sep 2021 12:58:34 +0100 Subject: [PATCH 075/107] Refactored test_plugin to closer to original --- tests/test_plugins.py | 41 +++++++++++++++++++++++++++++------------ 1 file changed, 29 insertions(+), 12 deletions(-) diff --git a/tests/test_plugins.py b/tests/test_plugins.py index 1a5dd2c3..3d7e56ec 100644 --- a/tests/test_plugins.py +++ b/tests/test_plugins.py @@ -11,27 +11,44 @@ class SnippetPluginsTestCase(CMSTestCase): def setUp(self): self.language = "en" self.superuser = self.get_superuser() - self.home = create_page( - title="home", template="page.html", - language=self.language, created_by=self.superuser, + title="home", + template="page.html", + language=self.language, + created_by=self.superuser, ) - title_data = { - "title": "home", "template": "page.html", "language": self.language, - "created_by": self.superuser, "page": self.home, - } - self.home_pagecontent = create_title(**title_data) self.page = create_page( - title="help", template="page.html", - language=self.language, created_by=self.superuser, + title="help", + template="page.html", + language=self.language, + created_by=self.superuser, + ) + self.page_pagecontent = create_title( + title="page", + template="page.html", + language=self.language, + created_by=self.superuser, + page=self.home, + ) + self.home_pagecontent = create_title( + title="home", + template="page.html", + language= self.language, + created_by= self.superuser, + page=self.home, ) - title_data["page"] = self.page - self.pagecontent = create_title(**title_data) + + self.placeholder = self.page.placeholders.get(slot="content") # Publish our page content self.home_pagecontent.versions.last().publish(user=self.superuser) self.pagecontent.versions.last().publish(user=self.superuser) + def tearDown(self): + self.page.delete() + self.home.delete() + self.superuser.delete() + def test_html_rendering(self): snippet = SnippetWithVersionFactory( name="plugin_snippet", From 315394064c65881c6524b49a377c1d3a6ad2badd Mon Sep 17 00:00:00 2001 From: Adam Murray Date: Wed, 15 Sep 2021 13:07:18 +0100 Subject: [PATCH 076/107] Refactoring tests --- tests/test_plugins.py | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/tests/test_plugins.py b/tests/test_plugins.py index 3d7e56ec..3704b1f6 100644 --- a/tests/test_plugins.py +++ b/tests/test_plugins.py @@ -28,21 +28,18 @@ def setUp(self): template="page.html", language=self.language, created_by=self.superuser, - page=self.home, + page=self.page, ) self.home_pagecontent = create_title( title="home", template="page.html", - language= self.language, - created_by= self.superuser, + language=self.language, + created_by=self.superuser, page=self.home, ) - - self.placeholder = self.page.placeholders.get(slot="content") - # Publish our page content - self.home_pagecontent.versions.last().publish(user=self.superuser) - self.pagecontent.versions.last().publish(user=self.superuser) + self.home_pagecontent.versions.first().publish(user=self.superuser) + self.page_pagecontent.versions.first().publish(user=self.superuser) def tearDown(self): self.page.delete() @@ -57,7 +54,7 @@ def test_html_rendering(self): ) snippet_grouper = snippet.snippet_grouper plugin = add_plugin( - self.pagecontent.placeholders.get(slot="content"), + self.page_pagecontent.placeholders.get(slot="content"), "SnippetPlugin", self.language, snippet_grouper=snippet_grouper, @@ -86,7 +83,7 @@ def test_failing_html_rendering(self): snippet.versions.last().publish(user=self.get_superuser()) add_plugin( - self.pagecontent.placeholders.get(slot="content"), + self.page_pagecontent.placeholders.get(slot="content"), "SnippetPlugin", self.language, snippet_grouper=snippet_grouper, @@ -109,7 +106,7 @@ def test_template_rendering(self): snippet_grouper = snippet.snippet_grouper snippet.versions.last().publish(user=self.get_superuser()) plugin = add_plugin( - self.pagecontent.placeholders.get(slot="content"), + self.page_pagecontent.placeholders.get(slot="content"), "SnippetPlugin", self.language, snippet_grouper=snippet_grouper, @@ -137,7 +134,7 @@ def test_failing_template_rendering(self): snippet_grouper = snippet.snippet_grouper snippet.versions.last().publish(user=self.get_superuser()) add_plugin( - self.pagecontent.placeholders.get(slot="content"), + self.page_pagecontent.placeholders.get(slot="content"), "SnippetPlugin", self.language, snippet_grouper=snippet_grouper, From 3d97dc8e7f0714c9c265a62538f115bb0d6f740f Mon Sep 17 00:00:00 2001 From: Adam Murray Date: Wed, 15 Sep 2021 13:22:35 +0100 Subject: [PATCH 077/107] Updated tests and migration to make grouper mandatory --- .../migrations/0012_auto_20210915_0721.py | 28 +++++++++++++++ .../0012_remove_snippetptr_snippet.py | 17 ---------- tests/test_plugins.py | 34 ++++++++++--------- 3 files changed, 46 insertions(+), 33 deletions(-) create mode 100644 djangocms_snippet/migrations/0012_auto_20210915_0721.py delete mode 100644 djangocms_snippet/migrations/0012_remove_snippetptr_snippet.py diff --git a/djangocms_snippet/migrations/0012_auto_20210915_0721.py b/djangocms_snippet/migrations/0012_auto_20210915_0721.py new file mode 100644 index 00000000..f57f106d --- /dev/null +++ b/djangocms_snippet/migrations/0012_auto_20210915_0721.py @@ -0,0 +1,28 @@ +# Generated by Django 2.2.24 on 2021-09-15 07:21 + +import django.db.models.deletion +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('djangocms_snippet', '0011_cms4_plugin_data_migration'), + ] + + operations = [ + migrations.RemoveField( + model_name='snippetptr', + name='snippet', + ), + migrations.AlterField( + model_name='snippet', + name='snippet_grouper', + field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='djangocms_snippet.SnippetGrouper'), + ), + migrations.AlterField( + model_name='snippetptr', + name='snippet_grouper', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='djangocms_snippet.SnippetGrouper'), + ), + ] diff --git a/djangocms_snippet/migrations/0012_remove_snippetptr_snippet.py b/djangocms_snippet/migrations/0012_remove_snippetptr_snippet.py deleted file mode 100644 index 8585fca6..00000000 --- a/djangocms_snippet/migrations/0012_remove_snippetptr_snippet.py +++ /dev/null @@ -1,17 +0,0 @@ -# Generated by Django 2.2.24 on 2021-09-15 05:06 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('djangocms_snippet', '0011_cms4_plugin_data_migration'), - ] - - operations = [ - migrations.RemoveField( - model_name='snippetptr', - name='snippet', - ), - ] diff --git a/tests/test_plugins.py b/tests/test_plugins.py index 3704b1f6..9e31b3f2 100644 --- a/tests/test_plugins.py +++ b/tests/test_plugins.py @@ -23,29 +23,31 @@ def setUp(self): language=self.language, created_by=self.superuser, ) - self.page_pagecontent = create_title( - title="page", - template="page.html", - language=self.language, - created_by=self.superuser, - page=self.page, - ) - self.home_pagecontent = create_title( - title="home", - template="page.html", - language=self.language, - created_by=self.superuser, - page=self.home, - ) # Publish our page content - self.home_pagecontent.versions.first().publish(user=self.superuser) - self.page_pagecontent.versions.first().publish(user=self.superuser) + self._publish(self.page) + self._publish(self.home) + self.page_pagecontent = self.page.pagecontent_set.last() + self.home_pagecontent = self.page.pagecontent_set.last() def tearDown(self): self.page.delete() self.home.delete() self.superuser.delete() + def _publish(self, grouper, language=None): + from djangocms_versioning.constants import DRAFT + version = self._get_version(grouper, DRAFT, language) + version.publish(self.superuser) + + def _get_version(self, grouper, version_state, language=None): + language = language or self.language + + from djangocms_versioning.models import Version + versions = Version.objects.filter_by_grouper(grouper).filter(state=version_state) + for version in versions: + if hasattr(version.content, 'language') and version.content.language == language: + return version + def test_html_rendering(self): snippet = SnippetWithVersionFactory( name="plugin_snippet", From 366739b0338e9bee7fe47fd79317546e6060018b Mon Sep 17 00:00:00 2001 From: Adam Murray Date: Wed, 15 Sep 2021 13:23:42 +0100 Subject: [PATCH 078/107] Updated models to even with migrations --- djangocms_snippet/models.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/djangocms_snippet/models.py b/djangocms_snippet/models.py index 2460d53d..d7094b10 100644 --- a/djangocms_snippet/models.py +++ b/djangocms_snippet/models.py @@ -26,8 +26,6 @@ class Snippet(models.Model): snippet_grouper = models.ForeignKey( SnippetGrouper, on_delete=models.PROTECT, - null=True, - blank=True, ) html = models.TextField( verbose_name=_('HTML'), @@ -75,8 +73,6 @@ class SnippetPtr(CMSPlugin): snippet_grouper = models.ForeignKey( SnippetGrouper, on_delete=models.CASCADE, - blank=True, - null=True, ) search_fields = ['snippet__html'] if SEARCH_ENABLED else [] From 3853d19b4b6bdd09dabc7becb0c043bdd0fc92f2 Mon Sep 17 00:00:00 2001 From: Adam Murray Date: Wed, 15 Sep 2021 13:26:28 +0100 Subject: [PATCH 079/107] Refactor --- tests/test_plugins.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/test_plugins.py b/tests/test_plugins.py index 9e31b3f2..0272d5ef 100644 --- a/tests/test_plugins.py +++ b/tests/test_plugins.py @@ -26,7 +26,7 @@ def setUp(self): # Publish our page content self._publish(self.page) self._publish(self.home) - self.page_pagecontent = self.page.pagecontent_set.last() + self.pagecontent = self.page.pagecontent_set.last() self.home_pagecontent = self.page.pagecontent_set.last() def tearDown(self): @@ -56,7 +56,7 @@ def test_html_rendering(self): ) snippet_grouper = snippet.snippet_grouper plugin = add_plugin( - self.page_pagecontent.placeholders.get(slot="content"), + self.pagecontent.placeholders.get(slot="content"), "SnippetPlugin", self.language, snippet_grouper=snippet_grouper, @@ -85,7 +85,7 @@ def test_failing_html_rendering(self): snippet.versions.last().publish(user=self.get_superuser()) add_plugin( - self.page_pagecontent.placeholders.get(slot="content"), + self.pagecontent.placeholders.get(slot="content"), "SnippetPlugin", self.language, snippet_grouper=snippet_grouper, @@ -108,7 +108,7 @@ def test_template_rendering(self): snippet_grouper = snippet.snippet_grouper snippet.versions.last().publish(user=self.get_superuser()) plugin = add_plugin( - self.page_pagecontent.placeholders.get(slot="content"), + self.pagecontent.placeholders.get(slot="content"), "SnippetPlugin", self.language, snippet_grouper=snippet_grouper, @@ -136,7 +136,7 @@ def test_failing_template_rendering(self): snippet_grouper = snippet.snippet_grouper snippet.versions.last().publish(user=self.get_superuser()) add_plugin( - self.page_pagecontent.placeholders.get(slot="content"), + self.pagecontent.placeholders.get(slot="content"), "SnippetPlugin", self.language, snippet_grouper=snippet_grouper, From e958a035bea611d75394270ac4b9068707095a84 Mon Sep 17 00:00:00 2001 From: Adam Murray Date: Wed, 15 Sep 2021 13:27:14 +0100 Subject: [PATCH 080/107] Linting --- tests/test_plugins.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_plugins.py b/tests/test_plugins.py index 0272d5ef..db1a0fe3 100644 --- a/tests/test_plugins.py +++ b/tests/test_plugins.py @@ -1,4 +1,4 @@ -from cms.api import add_plugin, create_page, create_title +from cms.api import add_plugin, create_page from cms.test_utils.testcases import CMSTestCase from .utils.factories import ( From dbfb8082bb954c0c5077bae22ac8f177a506a8d1 Mon Sep 17 00:00:00 2001 From: Adam Murray Date: Wed, 15 Sep 2021 13:52:56 +0100 Subject: [PATCH 081/107] Added migration and change for removing unique=True, allowing versioning to function --- djangocms_snippet/cms_config.py | 2 +- .../migrations/0013_auto_20210915_0751.py | 23 +++++++++++++++++++ djangocms_snippet/models.py | 2 -- tests/utils/utils.py | 15 ------------ 4 files changed, 24 insertions(+), 18 deletions(-) create mode 100644 djangocms_snippet/migrations/0013_auto_20210915_0751.py delete mode 100644 tests/utils/utils.py diff --git a/djangocms_snippet/cms_config.py b/djangocms_snippet/cms_config.py index da802c85..9ce10643 100644 --- a/djangocms_snippet/cms_config.py +++ b/djangocms_snippet/cms_config.py @@ -2,7 +2,7 @@ from cms.app_base import CMSAppConfig -from .models import Snippet +from djangocms_snippet.models import Snippet def _get_model_fields(instance, model, field_exclusion_list=[]): diff --git a/djangocms_snippet/migrations/0013_auto_20210915_0751.py b/djangocms_snippet/migrations/0013_auto_20210915_0751.py new file mode 100644 index 00000000..de813001 --- /dev/null +++ b/djangocms_snippet/migrations/0013_auto_20210915_0751.py @@ -0,0 +1,23 @@ +# Generated by Django 2.2.24 on 2021-09-15 07:51 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('djangocms_snippet', '0012_auto_20210915_0721'), + ] + + operations = [ + migrations.AlterField( + model_name='snippet', + name='name', + field=models.CharField(max_length=255, verbose_name='Name'), + ), + migrations.AlterField( + model_name='snippet', + name='slug', + field=models.SlugField(default='', max_length=255, verbose_name='Slug'), + ), + ] diff --git a/djangocms_snippet/models.py b/djangocms_snippet/models.py index d7094b10..c5b0a34e 100644 --- a/djangocms_snippet/models.py +++ b/djangocms_snippet/models.py @@ -21,7 +21,6 @@ class Snippet(models.Model): name = models.CharField( verbose_name=_('Name'), max_length=255, - unique=True, ) snippet_grouper = models.ForeignKey( SnippetGrouper, @@ -46,7 +45,6 @@ class Snippet(models.Model): blank=False, default='', max_length=255, - unique=True, ) def __str__(self): diff --git a/tests/utils/utils.py b/tests/utils/utils.py deleted file mode 100644 index 22c38d43..00000000 --- a/tests/utils/utils.py +++ /dev/null @@ -1,15 +0,0 @@ -from djangocms_snippet.cms_config import SnippetCMSAppConfig - - -try: - from djangocms_versioning import __version__ # NOQA - versioning_installed = True -except ImportError: - versioning_installed = False - - -def is_versioning_enabled(): - if SnippetCMSAppConfig.djangocms_versioning_enabled and versioning_installed: - return True - else: - return False From 8e599f3d8a573b18fc58c730bb6a20852274afda Mon Sep 17 00:00:00 2001 From: Adam Murray Date: Wed, 15 Sep 2021 13:59:10 +0100 Subject: [PATCH 082/107] Added checks for whether moderation is enabled --- djangocms_snippet/cms_config.py | 17 ++++++++++++++--- tests/settings.py | 1 + 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/djangocms_snippet/cms_config.py b/djangocms_snippet/cms_config.py index 9ce10643..dfd7cc1b 100644 --- a/djangocms_snippet/cms_config.py +++ b/djangocms_snippet/cms_config.py @@ -5,6 +5,14 @@ from djangocms_snippet.models import Snippet +try: + from djangocms_moderation import __version__ + + djangocms_moderation_installed = True +except ImportError: + djangocms_moderation_installed = False + + def _get_model_fields(instance, model, field_exclusion_list=[]): """ Iterate over fields excluding @@ -34,10 +42,13 @@ class SnippetCMSAppConfig(CMSAppConfig): djangocms_versioning_enabled = getattr( settings, 'DJANGOCMS_SNIPPET_VERSIONING_ENABLED', False ) + djangocms_moderation_enabled = getattr( + settings, 'DJANGOCMS_SNIPPET_MODERATION_ENABLED', False + ) - # TODO: Update this to check if moderation is installed and enabled - djangocms_moderation_enabled = True - moderated_models = [] + if djangocms_moderation_enabled and djangocms_moderation_installed: + djangocms_moderation_enabled = True + moderated_models = [Snippet] if djangocms_versioning_enabled: from djangocms_versioning.datastructures import ( diff --git a/tests/settings.py b/tests/settings.py index 23c4edd3..67f86952 100644 --- a/tests/settings.py +++ b/tests/settings.py @@ -14,6 +14,7 @@ 'LANGUAGE_CODE': 'en', 'ALLOWED_HOSTS': ['localhost'], 'DJANGOCMS_SNIPPET_VERSIONING_ENABLED': True, + 'DJANGOCMS_SNIPPET_MODERATION_ENABLED': True, } From 20ed1c890b6e2fa6176096e05f267ba0692be838 Mon Sep 17 00:00:00 2001 From: Adam Murray Date: Wed, 15 Sep 2021 14:01:17 +0100 Subject: [PATCH 083/107] Linting --- djangocms_snippet/cms_config.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/djangocms_snippet/cms_config.py b/djangocms_snippet/cms_config.py index dfd7cc1b..423f35b3 100644 --- a/djangocms_snippet/cms_config.py +++ b/djangocms_snippet/cms_config.py @@ -6,7 +6,7 @@ try: - from djangocms_moderation import __version__ + from djangocms_moderation import __version__ # NOQA djangocms_moderation_installed = True except ImportError: @@ -51,9 +51,7 @@ class SnippetCMSAppConfig(CMSAppConfig): moderated_models = [Snippet] if djangocms_versioning_enabled: - from djangocms_versioning.datastructures import ( - VersionableItem, - ) + from djangocms_versioning.datastructures import VersionableItem versioning = [ VersionableItem( From 463fd7c2cbfec968412daab548b91bdbbe5bda29 Mon Sep 17 00:00:00 2001 From: Adam Murray Date: Wed, 15 Sep 2021 14:02:33 +0100 Subject: [PATCH 084/107] Linting --- djangocms_snippet/cms_config.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/djangocms_snippet/cms_config.py b/djangocms_snippet/cms_config.py index 423f35b3..471aab0f 100644 --- a/djangocms_snippet/cms_config.py +++ b/djangocms_snippet/cms_config.py @@ -6,7 +6,7 @@ try: - from djangocms_moderation import __version__ # NOQA + from djangocms_moderation import __version__ # NOQA djangocms_moderation_installed = True except ImportError: From 32117b41c2e7bf4022257aa2089b060eb3985602 Mon Sep 17 00:00:00 2001 From: Adam Murray Date: Thu, 16 Sep 2021 11:03:07 +0100 Subject: [PATCH 085/107] Updated test and versioning admin class generation --- djangocms_snippet/admin.py | 32 +++++++++++++++++++++++++++++++- tests/test_admin.py | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+), 1 deletion(-) create mode 100644 tests/test_admin.py diff --git a/djangocms_snippet/admin.py b/djangocms_snippet/admin.py index 9187fadd..55a2d27c 100644 --- a/djangocms_snippet/admin.py +++ b/djangocms_snippet/admin.py @@ -6,7 +6,15 @@ from .models import Snippet -class SnippetAdmin(admin.ModelAdmin): +try: + from djangocms_versioning.admin import ExtendedVersionAdminMixin + + djangocms_versioning_installed = True +except ImportError: + djangocms_versioning_installed = False + + +class AbstractSnippetAdmin(admin.ModelAdmin): list_display = ('slug', 'name') search_fields = ['slug', 'name'] prepopulated_fields = {'slug': ('name',)} @@ -22,5 +30,27 @@ class SnippetAdmin(admin.ModelAdmin): models.TextField: {'widget': Textarea(attrs=text_area_attrs)} } + class Meta: + abstract = True + + + +djangocms_versioning_enabled = getattr( + settings, 'DJANGOCMS_SNIPPET_VERSIONING_ENABLED', False +) + +snippet_admin_classes = [ + AbstractSnippetAdmin, +] + + +if djangocms_versioning_installed and djangocms_versioning_enabled: + snippet_admin_classes = [ExtendedVersionAdminMixin] + snippet_admin_classes + + +class SnippetAdmin(*snippet_admin_classes): + class Meta: + model = Snippet + admin.site.register(Snippet, SnippetAdmin) diff --git a/tests/test_admin.py b/tests/test_admin.py new file mode 100644 index 00000000..b680420c --- /dev/null +++ b/tests/test_admin.py @@ -0,0 +1,34 @@ +from django.contrib import admin +from django.test import override_settings, RequestFactory + + +from cms.test_utils.testcases import CMSTestCase + +from djangocms_snippet.admin import AbstractSnippetAdmin, SnippetAdmin +from djangocms_snippet.models import Snippet + +from .utils.factories import SnippetWithVersionFactory + + +class SnippetAdminTestCase(CMSTestCase): + def setUp(self): + self.snippet = SnippetWithVersionFactory() + self.snippet_admin = SnippetAdmin(Snippet, admin) + self.snippet_admin_request = RequestFactory().get("/admin/djangocms_snippet") + + @override_settings(DJANGOCMS_SNIPPET_VERSIONING_ENABLED=False) + def test_admin_without_versioning(self): + list_display = self.snippet_admin.get_list_display(self.snippet_admin_request) + + self.assertEqual(self.snippet_admin.__class__.__bases__, (AbstractSnippetAdmin)) + self.assertEqual(list_display, ('slug', 'name')) + + def test_admin_with_versioning(self): + from djangocms_versioning.admin import ExtendedVersionAdminMixin + list_display = self.snippet_admin.get_list_display(self.snippet_admin_request) + import pdb + pdb.set_trace() + + self.assertEqual(self.snippet_admin.__class__.__bases__, (ExtendedVersionAdminMixin, AbstractSnippetAdmin)) + self.assertEqual(list_display, ('slug', 'name')) + From 868030ed251f9f37c55bbe3af984330350a1cdb5 Mon Sep 17 00:00:00 2001 From: Adam Murray Date: Fri, 17 Sep 2021 13:12:20 +0100 Subject: [PATCH 086/107] Implemented proper form and tests --- djangocms_snippet/forms.py | 63 ++++++++++++++++++++ tests/test_forms.py | 115 +++++++++++++++++++++++++++++++++++++ 2 files changed, 178 insertions(+) create mode 100644 djangocms_snippet/forms.py create mode 100644 tests/test_forms.py diff --git a/djangocms_snippet/forms.py b/djangocms_snippet/forms.py new file mode 100644 index 00000000..13b07926 --- /dev/null +++ b/djangocms_snippet/forms.py @@ -0,0 +1,63 @@ +from django import forms +from django.conf import settings +from django.utils.translation import ugettext_lazy as _ + +from djangocms_snippet.models import Snippet, SnippetGrouper + + +try: + from djangocms_versioning.models import Version + is_versioning_installed = True +except ImportError: + is_versioning_installed = False + +djangocms_versioning_enabled = getattr( + settings, 'DJANGOCMS_SNIPPET_VERSIONING_ENABLED', False + ) + + +class SnippetForm(forms.ModelForm): + class Meta: + model = Snippet + fields = ( + "name", + "html", + "slug", + "snippet_grouper", + ) + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self.fields["snippet_grouper"].required = False + + def clean(self): + data = super().clean() + name = data.get("name") + slug = data.get("slug") + snippet_grouper = data.get("snippet_grouper") + published_snippet_queryset = Snippet.objects.all() + + if djangocms_versioning_enabled and is_versioning_installed: + if snippet_grouper: + published_snippet_queryset.exclude(snippet_grouper=snippet_grouper) + + for snippet in published_snippet_queryset: + if snippet.name == name: + self.add_error( + "name", _("Snippet with this name already exists") + ) + elif snippet.slug == slug: + self.add_error( + "slug", _("Snippet with this slug already exists") + ) + + return data + + def save(self, **kwargs): + if not self.cleaned_data.get("snippet_grouper"): + super().save(commit=False) + self.instance.snippet_grouper = SnippetGrouper.objects.create() + # self.instance.snippet_grouper_id = self.snippet_grouper.id + return super().save() + + diff --git a/tests/test_forms.py b/tests/test_forms.py new file mode 100644 index 00000000..458e741a --- /dev/null +++ b/tests/test_forms.py @@ -0,0 +1,115 @@ +from django.test import override_settings + +from cms.test_utils.testcases import CMSTestCase + +from djangocms_snippet.forms import SnippetForm +from djangocms_snippet.models import Snippet, SnippetGrouper + + +class SnippetFormTestCase(CMSTestCase): + + @override_settings(DJANGOCMS_SNIPPET_VERSIONING_ENABLED=False) + def test_snippet_form_creates_grouper_no_versioning(self): + """ + Without versioning enabled, the application still has the grouper implemented, therefore the form + should be creating one for each new snippet created. + """ + form_data = { + "name": "test_snippet", + "slug": "test_snippet", + "html": "

Test Title

" + } + form = SnippetForm(form_data) + + self.assertTrue(form.is_valid()) + + form.clean() + form.save() + + self.assertEqual(SnippetGrouper.objects.count(), 1) + + def test_snippet_form_creates_grouper_with_versioning(self): + """ + With versioning enabled, groupers should also be created in the background. + """ + form_data = { + "name": "test_snippet", + "slug": "test_snippet", + "html": "

Test Title

" + } + form = SnippetForm(form_data) + + self.assertTrue(form.is_valid()) + + form.clean() + form.save() + + self.assertEqual(SnippetGrouper.objects.count(), 1) + + def test_snippet_form_adds_to_existing_grouper_with_versioning(self): + """ + With versioning enabled, if a grouper already exists, a new one shouldn't be created + """ + + grouper = SnippetGrouper.objects.create() + form_data = { + "name": "test_snippet", + "slug": "test_snippet", + "html": "

Test Title

", + "snippet_grouper": grouper.id, + } + form = SnippetForm(form_data) + + self.assertTrue(form.is_valid()) + + form.clean() + form.save() + + self.assertEqual(SnippetGrouper.objects.count(), 1) + + form_data["html"] = "

Test Title

" + + form = SnippetForm(form_data) + + self.assertTrue(form.is_valid()) + + form.clean() + form.save() + + self.assertEqual(SnippetGrouper.objects.count(), 1) + + def test_snippet_form_versioning_enabled(self): + """ + With versioning enabled, the snippet form doesn't have to create groupers, but does have to validate + that no other active (i.e. the latest published snippet from a given grouper) shares the same name or slug. + """ + form_data = { + "name": "test_snippet", + "slug": "test_snippet", + "html": "

Test Title

", + } + form = SnippetForm(form_data) + + self.assertTrue(form.is_valid()) + + # Clean and save the form + form.clean() + form.save() + + snippet = Snippet._base_manager.last() + version = snippet.versions.create(created_by=self.get_superuser()) + version.publish(user=self.get_superuser()) + + new_form_data = { + "name": "test_snippet1", + "slug": "test_snippet", + "html": "

Another Test Title

", + } + + new_form = SnippetForm(new_form_data) + + self.assertFalse(new_form.is_valid()) + + new_form.clean() + + self.assertDictEqual(new_form.errors, {'slug': ['Snippet with this slug already exists']}) From 5966b486e90e52058010c193196d2f6de0245840 Mon Sep 17 00:00:00 2001 From: Adam Murray Date: Fri, 17 Sep 2021 13:14:27 +0100 Subject: [PATCH 087/107] Remove commented out code --- djangocms_snippet/forms.py | 1 - 1 file changed, 1 deletion(-) diff --git a/djangocms_snippet/forms.py b/djangocms_snippet/forms.py index 13b07926..bc98bb47 100644 --- a/djangocms_snippet/forms.py +++ b/djangocms_snippet/forms.py @@ -57,7 +57,6 @@ def save(self, **kwargs): if not self.cleaned_data.get("snippet_grouper"): super().save(commit=False) self.instance.snippet_grouper = SnippetGrouper.objects.create() - # self.instance.snippet_grouper_id = self.snippet_grouper.id return super().save() From f27255ae1bc793588eae8a7c20d317be8e51d739 Mon Sep 17 00:00:00 2001 From: Adam Murray Date: Fri, 17 Sep 2021 15:47:27 +0100 Subject: [PATCH 088/107] Fixed tests --- djangocms_snippet/forms.py | 4 ++-- tests/test_admin.py | 21 ++++++++++++++------- tests/test_forms.py | 2 +- 3 files changed, 17 insertions(+), 10 deletions(-) diff --git a/djangocms_snippet/forms.py b/djangocms_snippet/forms.py index bc98bb47..63978f94 100644 --- a/djangocms_snippet/forms.py +++ b/djangocms_snippet/forms.py @@ -44,11 +44,11 @@ def clean(self): for snippet in published_snippet_queryset: if snippet.name == name: self.add_error( - "name", _("Snippet with this name already exists") + "name", _("A Snippet with this name already exists") ) elif snippet.slug == slug: self.add_error( - "slug", _("Snippet with this slug already exists") + "slug", _("A Snippet with this slug already exists") ) return data diff --git a/tests/test_admin.py b/tests/test_admin.py index b680420c..39ad661f 100644 --- a/tests/test_admin.py +++ b/tests/test_admin.py @@ -1,10 +1,12 @@ +from importlib import reload + from django.contrib import admin from django.test import override_settings, RequestFactory from cms.test_utils.testcases import CMSTestCase -from djangocms_snippet.admin import AbstractSnippetAdmin, SnippetAdmin +from djangocms_snippet import admin as snippet_admin from djangocms_snippet.models import Snippet from .utils.factories import SnippetWithVersionFactory @@ -13,22 +15,27 @@ class SnippetAdminTestCase(CMSTestCase): def setUp(self): self.snippet = SnippetWithVersionFactory() - self.snippet_admin = SnippetAdmin(Snippet, admin) + self.snippet_admin = snippet_admin.SnippetAdmin(Snippet, admin) self.snippet_admin_request = RequestFactory().get("/admin/djangocms_snippet") @override_settings(DJANGOCMS_SNIPPET_VERSIONING_ENABLED=False) def test_admin_without_versioning(self): + admin.site.unregister(Snippet) + reload(snippet_admin) + self.snippet_admin = snippet_admin.SnippetAdmin(Snippet, admin) + list_display = self.snippet_admin.get_list_display(self.snippet_admin_request) - self.assertEqual(self.snippet_admin.__class__.__bases__, (AbstractSnippetAdmin)) + self.assertEqual(self.snippet_admin.__class__.__bases__, (snippet_admin.AbstractSnippetAdmin,)) self.assertEqual(list_display, ('slug', 'name')) def test_admin_with_versioning(self): from djangocms_versioning.admin import ExtendedVersionAdminMixin list_display = self.snippet_admin.get_list_display(self.snippet_admin_request) - import pdb - pdb.set_trace() - self.assertEqual(self.snippet_admin.__class__.__bases__, (ExtendedVersionAdminMixin, AbstractSnippetAdmin)) - self.assertEqual(list_display, ('slug', 'name')) + self.assertEqual( + self.snippet_admin.__class__.__bases__, (ExtendedVersionAdminMixin, snippet_admin.AbstractSnippetAdmin) + ) + self.assertEqual(list_display[:-1], ('slug', 'name', 'get_author', 'get_modified_date', 'get_versioning_state')) + self.assertEqual(list_display[-1].short_description, 'actions') diff --git a/tests/test_forms.py b/tests/test_forms.py index 458e741a..98e4a1e6 100644 --- a/tests/test_forms.py +++ b/tests/test_forms.py @@ -112,4 +112,4 @@ def test_snippet_form_versioning_enabled(self): new_form.clean() - self.assertDictEqual(new_form.errors, {'slug': ['Snippet with this slug already exists']}) + self.assertDictEqual(new_form.errors, {'slug': ['A Snippet with this slug already exists']}) From 93c450c91a64bf911b1cb3f150812b8099580cfc Mon Sep 17 00:00:00 2001 From: Adam Murray Date: Fri, 17 Sep 2021 17:21:30 +0100 Subject: [PATCH 089/107] Remoce Unique=True on slug and name --- djangocms_snippet/models.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/djangocms_snippet/models.py b/djangocms_snippet/models.py index d7094b10..c5b0a34e 100644 --- a/djangocms_snippet/models.py +++ b/djangocms_snippet/models.py @@ -21,7 +21,6 @@ class Snippet(models.Model): name = models.CharField( verbose_name=_('Name'), max_length=255, - unique=True, ) snippet_grouper = models.ForeignKey( SnippetGrouper, @@ -46,7 +45,6 @@ class Snippet(models.Model): blank=False, default='', max_length=255, - unique=True, ) def __str__(self): From 65a317522442a19cdecdada4fbf5894bac3a51d9 Mon Sep 17 00:00:00 2001 From: Adam Murray Date: Fri, 17 Sep 2021 17:32:43 +0100 Subject: [PATCH 090/107] Linting --- djangocms_snippet/admin.py | 1 - djangocms_snippet/forms.py | 4 +--- tests/test_admin.py | 5 +++-- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/djangocms_snippet/admin.py b/djangocms_snippet/admin.py index 55a2d27c..34188f0f 100644 --- a/djangocms_snippet/admin.py +++ b/djangocms_snippet/admin.py @@ -34,7 +34,6 @@ class Meta: abstract = True - djangocms_versioning_enabled = getattr( settings, 'DJANGOCMS_SNIPPET_VERSIONING_ENABLED', False ) diff --git a/djangocms_snippet/forms.py b/djangocms_snippet/forms.py index 63978f94..487f2965 100644 --- a/djangocms_snippet/forms.py +++ b/djangocms_snippet/forms.py @@ -6,7 +6,7 @@ try: - from djangocms_versioning.models import Version + from djangocms_versioning import __version__ # NOQA is_versioning_installed = True except ImportError: is_versioning_installed = False @@ -58,5 +58,3 @@ def save(self, **kwargs): super().save(commit=False) self.instance.snippet_grouper = SnippetGrouper.objects.create() return super().save() - - diff --git a/tests/test_admin.py b/tests/test_admin.py index 39ad661f..dcfdbb9c 100644 --- a/tests/test_admin.py +++ b/tests/test_admin.py @@ -36,6 +36,7 @@ def test_admin_with_versioning(self): self.assertEqual( self.snippet_admin.__class__.__bases__, (ExtendedVersionAdminMixin, snippet_admin.AbstractSnippetAdmin) ) - self.assertEqual(list_display[:-1], ('slug', 'name', 'get_author', 'get_modified_date', 'get_versioning_state')) + self.assertEqual( + list_display[:-1], ('slug', 'name', 'get_author', 'get_modified_date', 'get_versioning_state') + ) self.assertEqual(list_display[-1].short_description, 'actions') - From c61190c86970a7945a8428f9c57e64ba1ce5046d Mon Sep 17 00:00:00 2001 From: Adam Murray Date: Fri, 17 Sep 2021 17:35:40 +0100 Subject: [PATCH 091/107] iSort --- djangocms_snippet/forms.py | 2 +- tests/test_admin.py | 3 +-- tests/test_plugins.py | 4 +--- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/djangocms_snippet/forms.py b/djangocms_snippet/forms.py index 487f2965..b8f226f6 100644 --- a/djangocms_snippet/forms.py +++ b/djangocms_snippet/forms.py @@ -6,7 +6,7 @@ try: - from djangocms_versioning import __version__ # NOQA + from djangocms_versioning import __version__ # NOQA is_versioning_installed = True except ImportError: is_versioning_installed = False diff --git a/tests/test_admin.py b/tests/test_admin.py index dcfdbb9c..8b15aecc 100644 --- a/tests/test_admin.py +++ b/tests/test_admin.py @@ -1,8 +1,7 @@ from importlib import reload from django.contrib import admin -from django.test import override_settings, RequestFactory - +from django.test import RequestFactory, override_settings from cms.test_utils.testcases import CMSTestCase diff --git a/tests/test_plugins.py b/tests/test_plugins.py index db1a0fe3..ba901439 100644 --- a/tests/test_plugins.py +++ b/tests/test_plugins.py @@ -1,9 +1,7 @@ from cms.api import add_plugin, create_page from cms.test_utils.testcases import CMSTestCase -from .utils.factories import ( - SnippetWithVersionFactory, -) +from .utils.factories import SnippetWithVersionFactory class SnippetPluginsTestCase(CMSTestCase): From a500c9a8f3c3ede0d5768c02cc139a993b144394 Mon Sep 17 00:00:00 2001 From: Adam Murray Date: Fri, 17 Sep 2021 17:46:05 +0100 Subject: [PATCH 092/107] Added test criteria and comments for admin --- tests/test_admin.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/tests/test_admin.py b/tests/test_admin.py index 8b15aecc..662b474f 100644 --- a/tests/test_admin.py +++ b/tests/test_admin.py @@ -18,7 +18,10 @@ def setUp(self): self.snippet_admin_request = RequestFactory().get("/admin/djangocms_snippet") @override_settings(DJANGOCMS_SNIPPET_VERSIONING_ENABLED=False) - def test_admin_without_versioning(self): + def test_admin_list_display_without_versioning(self): + """ + Without versioning enabled, list_display should not be extended with version related items + """ admin.site.unregister(Snippet) reload(snippet_admin) self.snippet_admin = snippet_admin.SnippetAdmin(Snippet, admin) @@ -28,7 +31,11 @@ def test_admin_without_versioning(self): self.assertEqual(self.snippet_admin.__class__.__bases__, (snippet_admin.AbstractSnippetAdmin,)) self.assertEqual(list_display, ('slug', 'name')) - def test_admin_with_versioning(self): + def test_admin_list_display_with_versioning(self): + """ + With versioning enabled, list_display should be populated with both versioning related items, and the + list actions items + """ from djangocms_versioning.admin import ExtendedVersionAdminMixin list_display = self.snippet_admin.get_list_display(self.snippet_admin_request) @@ -39,3 +46,4 @@ def test_admin_with_versioning(self): list_display[:-1], ('slug', 'name', 'get_author', 'get_modified_date', 'get_versioning_state') ) self.assertEqual(list_display[-1].short_description, 'actions') + self.assertIn("function ExtendedVersionAdminMixin._list_actions", list_display[-1].__str__()) From b8f7367adcf7372220bc1b74785c749030ff7bd5 Mon Sep 17 00:00:00 2001 From: Adam Murray Date: Fri, 17 Sep 2021 17:57:25 +0100 Subject: [PATCH 093/107] Fixed form save method issue found in manual testing --- djangocms_snippet/forms.py | 1 + 1 file changed, 1 insertion(+) diff --git a/djangocms_snippet/forms.py b/djangocms_snippet/forms.py index b8f226f6..26fb6571 100644 --- a/djangocms_snippet/forms.py +++ b/djangocms_snippet/forms.py @@ -56,5 +56,6 @@ def clean(self): def save(self, **kwargs): if not self.cleaned_data.get("snippet_grouper"): super().save(commit=False) + self.save_m2m() self.instance.snippet_grouper = SnippetGrouper.objects.create() return super().save() From 4ac015d13312d542f84896135e0f6561825f3bb9 Mon Sep 17 00:00:00 2001 From: Adam Murray Date: Wed, 22 Sep 2021 15:51:00 +0100 Subject: [PATCH 094/107] Push or placeholder problems --- djangocms_snippet/admin.py | 35 ++++++++++++++++++- djangocms_snippet/cms_config.py | 6 +++- djangocms_snippet/models.py | 9 +++++ djangocms_snippet/rendering.py | 7 ++++ .../djangocms_snippet/admin/preview.html | 13 +++++++ djangocms_snippet/urls.py | 16 +++++++++ djangocms_snippet/views.py | 5 +++ 7 files changed, 89 insertions(+), 2 deletions(-) create mode 100644 djangocms_snippet/rendering.py create mode 100644 djangocms_snippet/templates/djangocms_snippet/admin/preview.html create mode 100644 djangocms_snippet/urls.py create mode 100644 djangocms_snippet/views.py diff --git a/djangocms_snippet/admin.py b/djangocms_snippet/admin.py index 34188f0f..d8d72160 100644 --- a/djangocms_snippet/admin.py +++ b/djangocms_snippet/admin.py @@ -1,10 +1,13 @@ from django.conf import settings +from django.conf.urls import url from django.contrib import admin from django.db import models from django.forms import Textarea -from .models import Snippet +from cms.toolbar.utils import get_object_preview_url +from .models import Snippet +from .views import SnippetPreviewView try: from djangocms_versioning.admin import ExtendedVersionAdminMixin @@ -51,5 +54,35 @@ class SnippetAdmin(*snippet_admin_classes): class Meta: model = Snippet + def get_urls(self): + info = self.model._meta.app_label, self.model._meta.model_name + return [ + url( + r"^$", + self.admin_site.admin_view(self.changelist_view), + name="{}_{}_changelist".format(*info), + ), + url( + r"^(?P\d+)/$", + self.admin_site.admin_view(self.changelist_view), + name="{}_{}_list".format(*info), + ), + url( + r"^add/$", + self.admin_site.admin_view(self.add_view), + name="{}_{}_add".format(*info), + ), + url( + r"^(?P\d+)/change/$", + self.admin_site.admin_view(self.change_view), + name="{}_{}_change".format(*info), + ), + url( + r"^(?P\d+)/preview/$", + self.admin_site.admin_view(SnippetPreviewView.as_view()), + name="{}_{}_preview".format(*info), + ), + ] + admin.site.register(Snippet, SnippetAdmin) diff --git a/djangocms_snippet/cms_config.py b/djangocms_snippet/cms_config.py index c23f2cd1..1e8f92bc 100644 --- a/djangocms_snippet/cms_config.py +++ b/djangocms_snippet/cms_config.py @@ -1,9 +1,10 @@ from django.conf import settings from cms.app_base import CMSAppConfig +from cms.views import render_object_preview from djangocms_snippet.models import Snippet - +from djangocms_snippet.rendering import render_snippet try: from djangocms_moderation import __version__ # NOQA @@ -21,6 +22,9 @@ class SnippetCMSAppConfig(CMSAppConfig): settings, 'DJANGOCMS_SNIPPET_MODERATION_ENABLED', False ) + cms_enabled = True + cms_toolbar_enabled_models = [(Snippet, render_snippet),] + if djangocms_moderation_enabled and djangocms_moderation_installed: moderated_models = [Snippet] diff --git a/djangocms_snippet/models.py b/djangocms_snippet/models.py index c5b0a34e..c774cc7f 100644 --- a/djangocms_snippet/models.py +++ b/djangocms_snippet/models.py @@ -1,5 +1,6 @@ from django.conf import settings from django.db import models +from django.shortcuts import reverse from django.utils.translation import gettext_lazy as _ from cms.models import CMSPlugin @@ -50,6 +51,14 @@ class Snippet(models.Model): def __str__(self): return self.name + def get_preview_url(self): + return reverse( + "admin:{app}_{model}_preview".format( + app=self._meta.app_label, model=self._meta.model_name, + ), + args=[self.id], + ) + class Meta: ordering = ['name'] verbose_name = _('Snippet') diff --git a/djangocms_snippet/rendering.py b/djangocms_snippet/rendering.py new file mode 100644 index 00000000..9525b4d5 --- /dev/null +++ b/djangocms_snippet/rendering.py @@ -0,0 +1,7 @@ +from django.template.response import TemplateResponse + + +def render_snippet(request, snippet): + template = 'djangocms_snippet/admin/preview.html' + context = {'snippet': snippet} + return TemplateResponse(request, template, context) diff --git a/djangocms_snippet/templates/djangocms_snippet/admin/preview.html b/djangocms_snippet/templates/djangocms_snippet/admin/preview.html new file mode 100644 index 00000000..41d7f00c --- /dev/null +++ b/djangocms_snippet/templates/djangocms_snippet/admin/preview.html @@ -0,0 +1,13 @@ +{% extends "admin/base_site.html" %} +{% load i18n admin_urls static cms_tags %} + +{% block extrastyle %} + {{ block.super }} + +{% endblock %} + +{% block coltype %}flex{% endblock %} + +{% block bodyclass %}{{ block.super }} app-{{ opts.app_label }} model-{{ opts.model_name }} change-list{% endblock %} + +

Hello

diff --git a/djangocms_snippet/urls.py b/djangocms_snippet/urls.py new file mode 100644 index 00000000..b93d5a88 --- /dev/null +++ b/djangocms_snippet/urls.py @@ -0,0 +1,16 @@ +from django.conf.urls import url +from django.urls import include, path + +from cms.views import render_object_preview + +from djangocms_snippet.models import Snippet +from djangocms_snippet.views import SnippetPreviewView + + +urlpatterns = [ + url( + r"^(?P\d+)/preview/$", + SnippetPreviewView.as_view(), + name=f"{Snippet._meta.app_label}_{Snippet._meta.model_name}_preview" + ) +] diff --git a/djangocms_snippet/views.py b/djangocms_snippet/views.py new file mode 100644 index 00000000..2c5eba41 --- /dev/null +++ b/djangocms_snippet/views.py @@ -0,0 +1,5 @@ +from django.views.generic import TemplateView + + +class SnippetPreviewView(TemplateView): + template_name = "djangocms_snippet/admin/preview.html" From e251685666bb460a2baee6ecd9d2811e6220f9c3 Mon Sep 17 00:00:00 2001 From: Adam Murray Date: Fri, 8 Oct 2021 10:27:15 +0100 Subject: [PATCH 095/107] Preview view and testcase --- djangocms_snippet/admin.py | 2 -- .../djangocms_snippet/admin/preview.html | 9 ++++++-- djangocms_snippet/views.py | 13 +++++++++++ tests/test_views.py | 22 +++++++++++++++++++ 4 files changed, 42 insertions(+), 4 deletions(-) create mode 100644 tests/test_views.py diff --git a/djangocms_snippet/admin.py b/djangocms_snippet/admin.py index d8d72160..99307318 100644 --- a/djangocms_snippet/admin.py +++ b/djangocms_snippet/admin.py @@ -4,8 +4,6 @@ from django.db import models from django.forms import Textarea -from cms.toolbar.utils import get_object_preview_url - from .models import Snippet from .views import SnippetPreviewView diff --git a/djangocms_snippet/templates/djangocms_snippet/admin/preview.html b/djangocms_snippet/templates/djangocms_snippet/admin/preview.html index 41d7f00c..723b71b5 100644 --- a/djangocms_snippet/templates/djangocms_snippet/admin/preview.html +++ b/djangocms_snippet/templates/djangocms_snippet/admin/preview.html @@ -1,5 +1,6 @@ {% extends "admin/base_site.html" %} -{% load i18n admin_urls static cms_tags %} +{% load static %} +{{ snippet.html|safe|escape }} {% block extrastyle %} {{ block.super }} @@ -10,4 +11,8 @@ {% block bodyclass %}{{ block.super }} app-{{ opts.app_label }} model-{{ opts.model_name }} change-list{% endblock %} -

Hello

+{% block content %} + {% autoescape off %} + {{ snippet.html }} + {% endautoescape %} +{% endblock %} diff --git a/djangocms_snippet/views.py b/djangocms_snippet/views.py index 2c5eba41..721222cd 100644 --- a/djangocms_snippet/views.py +++ b/djangocms_snippet/views.py @@ -1,5 +1,18 @@ +from django.shortcuts import get_object_or_404 from django.views.generic import TemplateView +from djangocms_snippet.models import Snippet + class SnippetPreviewView(TemplateView): template_name = "djangocms_snippet/admin/preview.html" + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + snippet_qs = Snippet._base_manager.filter(pk=self.kwargs.get("snippet_id")) + snippet = snippet_qs[0] + context.update({ + "snippet": snippet, + "opts": Snippet._meta + }) + return context diff --git a/tests/test_views.py b/tests/test_views.py new file mode 100644 index 00000000..971f803f --- /dev/null +++ b/tests/test_views.py @@ -0,0 +1,22 @@ +from cms.test_utils.testcases import CMSTestCase +from cms.utils.urlutils import admin_reverse + +from .utils.factories import SnippetWithVersionFactory + + +class PreviewViewTestCase(CMSTestCase): + def setUp(self): + self.snippet = SnippetWithVersionFactory(html="

Test Title


Test paragraph

") + self.preview_url = admin_reverse( + "djangocms_snippet_snippet_preview", + kwargs={"snippet_id": self.snippet.id}, + ) + + def test_preview_renders_html(self): + self.snippet.versions.last().publish(user=self.get_superuser()) + with self.login_user_context(self.get_superuser()): + response = self.client.get(self.preview_url) + + self.assertEqual(self.snippet.html, "

Test Title


Test paragraph

") + self.assertEqual(response.status_code, 200) + self.assertContains(response, "

Test Title


Test paragraph

") From 426510f9e50933ba13ee8af1b4d7bb8c8090547e Mon Sep 17 00:00:00 2001 From: Adam Murray Date: Fri, 8 Oct 2021 10:35:05 +0100 Subject: [PATCH 096/107] Linting --- djangocms_snippet/admin.py | 1 + djangocms_snippet/cms_config.py | 1 + 2 files changed, 2 insertions(+) diff --git a/djangocms_snippet/admin.py b/djangocms_snippet/admin.py index 99307318..a8d46455 100644 --- a/djangocms_snippet/admin.py +++ b/djangocms_snippet/admin.py @@ -7,6 +7,7 @@ from .models import Snippet from .views import SnippetPreviewView + try: from djangocms_versioning.admin import ExtendedVersionAdminMixin diff --git a/djangocms_snippet/cms_config.py b/djangocms_snippet/cms_config.py index 1e8f92bc..b6e9cc55 100644 --- a/djangocms_snippet/cms_config.py +++ b/djangocms_snippet/cms_config.py @@ -6,6 +6,7 @@ from djangocms_snippet.models import Snippet from djangocms_snippet.rendering import render_snippet + try: from djangocms_moderation import __version__ # NOQA From 47dfedf736ee690465b58c8c99eb03e9460f4932 Mon Sep 17 00:00:00 2001 From: Adam Murray Date: Fri, 8 Oct 2021 11:02:55 +0100 Subject: [PATCH 097/107] Linting and additional test case --- djangocms_snippet/cms_config.py | 3 +-- djangocms_snippet/urls.py | 3 --- djangocms_snippet/views.py | 10 +++++++--- tests/requirements/dj22_cms37.txt | 4 ---- tests/requirements/dj22_cms38.txt | 4 ---- tests/requirements/dj30_cms37.txt | 4 ---- tests/requirements/dj30_cms38.txt | 4 ---- tests/requirements/dj31_cms38.txt | 4 ---- tests/test_views.py | 28 ++++++++++++++++++++++------ 9 files changed, 30 insertions(+), 34 deletions(-) delete mode 100644 tests/requirements/dj22_cms37.txt delete mode 100644 tests/requirements/dj22_cms38.txt delete mode 100644 tests/requirements/dj30_cms37.txt delete mode 100644 tests/requirements/dj30_cms38.txt delete mode 100644 tests/requirements/dj31_cms38.txt diff --git a/djangocms_snippet/cms_config.py b/djangocms_snippet/cms_config.py index b6e9cc55..a1b6c44d 100644 --- a/djangocms_snippet/cms_config.py +++ b/djangocms_snippet/cms_config.py @@ -1,7 +1,6 @@ from django.conf import settings from cms.app_base import CMSAppConfig -from cms.views import render_object_preview from djangocms_snippet.models import Snippet from djangocms_snippet.rendering import render_snippet @@ -24,7 +23,7 @@ class SnippetCMSAppConfig(CMSAppConfig): ) cms_enabled = True - cms_toolbar_enabled_models = [(Snippet, render_snippet),] + cms_toolbar_enabled_models = [(Snippet, render_snippet), ] if djangocms_moderation_enabled and djangocms_moderation_installed: moderated_models = [Snippet] diff --git a/djangocms_snippet/urls.py b/djangocms_snippet/urls.py index b93d5a88..2581523c 100644 --- a/djangocms_snippet/urls.py +++ b/djangocms_snippet/urls.py @@ -1,7 +1,4 @@ from django.conf.urls import url -from django.urls import include, path - -from cms.views import render_object_preview from djangocms_snippet.models import Snippet from djangocms_snippet.views import SnippetPreviewView diff --git a/djangocms_snippet/views.py b/djangocms_snippet/views.py index 721222cd..e47036da 100644 --- a/djangocms_snippet/views.py +++ b/djangocms_snippet/views.py @@ -1,4 +1,4 @@ -from django.shortcuts import get_object_or_404 +from django.http import Http404 from django.views.generic import TemplateView from djangocms_snippet.models import Snippet @@ -9,8 +9,12 @@ class SnippetPreviewView(TemplateView): def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) - snippet_qs = Snippet._base_manager.filter(pk=self.kwargs.get("snippet_id")) - snippet = snippet_qs[0] + + try: + snippet = Snippet._base_manager.get(pk=self.kwargs.get("snippet_id")) + except Snippet.DoesNotExist: + raise Http404 + context.update({ "snippet": snippet, "opts": Snippet._meta diff --git a/tests/requirements/dj22_cms37.txt b/tests/requirements/dj22_cms37.txt deleted file mode 100644 index 6b96a102..00000000 --- a/tests/requirements/dj22_cms37.txt +++ /dev/null @@ -1,4 +0,0 @@ --r base.txt - -Django>=2.2,<3.0 -django-cms>=3.7,<3.8 diff --git a/tests/requirements/dj22_cms38.txt b/tests/requirements/dj22_cms38.txt deleted file mode 100644 index 22c4fef2..00000000 --- a/tests/requirements/dj22_cms38.txt +++ /dev/null @@ -1,4 +0,0 @@ --r base.txt - -Django>=2.2,<3.0 -django-cms>=3.8,<3.9 diff --git a/tests/requirements/dj30_cms37.txt b/tests/requirements/dj30_cms37.txt deleted file mode 100644 index edcfd450..00000000 --- a/tests/requirements/dj30_cms37.txt +++ /dev/null @@ -1,4 +0,0 @@ --r base.txt - -Django>=3.0,<3.1 -django-cms>=3.7,<3.8 diff --git a/tests/requirements/dj30_cms38.txt b/tests/requirements/dj30_cms38.txt deleted file mode 100644 index 7bc3c0be..00000000 --- a/tests/requirements/dj30_cms38.txt +++ /dev/null @@ -1,4 +0,0 @@ --r base.txt - -Django>=3.0,<3.1 -django-cms>=3.8,<3.9 diff --git a/tests/requirements/dj31_cms38.txt b/tests/requirements/dj31_cms38.txt deleted file mode 100644 index d17fdb42..00000000 --- a/tests/requirements/dj31_cms38.txt +++ /dev/null @@ -1,4 +0,0 @@ --r base.txt - -Django>=3.1,<3.2 -django-cms>=3.8,<3.9 diff --git a/tests/test_views.py b/tests/test_views.py index 971f803f..ce3c7e5a 100644 --- a/tests/test_views.py +++ b/tests/test_views.py @@ -7,16 +7,32 @@ class PreviewViewTestCase(CMSTestCase): def setUp(self): self.snippet = SnippetWithVersionFactory(html="

Test Title


Test paragraph

") - self.preview_url = admin_reverse( + self.user = self.get_superuser() + + def test_preview_renders_html(self): + """ + Check that our snippet HTML is rendered, unescaped, on the page + """ + preview_url = admin_reverse( "djangocms_snippet_snippet_preview", kwargs={"snippet_id": self.snippet.id}, ) - - def test_preview_renders_html(self): - self.snippet.versions.last().publish(user=self.get_superuser()) - with self.login_user_context(self.get_superuser()): - response = self.client.get(self.preview_url) + with self.login_user_context(self.user): + response = self.client.get(preview_url) self.assertEqual(self.snippet.html, "

Test Title


Test paragraph

") self.assertEqual(response.status_code, 200) self.assertContains(response, "

Test Title


Test paragraph

") + + def test_preview_raises_404_no_snippet(self): + """ + With no Snippet to preview, a 404 will be raised + """ + preview_url = admin_reverse( + "djangocms_snippet_snippet_preview", + kwargs={"snippet_id": 999}, # Non existent PK! + ) + with self.login_user_context(self.user): + response = self.client.get(preview_url) + + self.assertEqual(response.status_code, 404) From a6919e8a4fb592ec6e23986b76108cdd0b5ea14f Mon Sep 17 00:00:00 2001 From: Adam Murray Date: Tue, 12 Oct 2021 10:39:13 +0100 Subject: [PATCH 098/107] Update djangocms_snippet/views.py Co-authored-by: Aiky30 --- djangocms_snippet/views.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/djangocms_snippet/views.py b/djangocms_snippet/views.py index e47036da..3b406d99 100644 --- a/djangocms_snippet/views.py +++ b/djangocms_snippet/views.py @@ -9,6 +9,10 @@ class SnippetPreviewView(TemplateView): def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) + snippet_id = kwargs.get("snippet_id", None) + + if not snippet_id: + Http404("snippet_id must be provided.") try: snippet = Snippet._base_manager.get(pk=self.kwargs.get("snippet_id")) From 7f654040b02b4f3938b319b571e8a49c5ecbbf81 Mon Sep 17 00:00:00 2001 From: Adam Murray Date: Tue, 12 Oct 2021 10:57:50 +0100 Subject: [PATCH 099/107] PR updates --- djangocms_snippet/admin.py | 33 +++++++++++++-------------------- djangocms_snippet/forms.py | 14 +++++++------- djangocms_snippet/urls.py | 13 ------------- tests/test_admin.py | 6 ++++-- 4 files changed, 24 insertions(+), 42 deletions(-) delete mode 100644 djangocms_snippet/urls.py diff --git a/djangocms_snippet/admin.py b/djangocms_snippet/admin.py index a8d46455..1c8b3a86 100644 --- a/djangocms_snippet/admin.py +++ b/djangocms_snippet/admin.py @@ -4,6 +4,7 @@ from django.db import models from django.forms import Textarea +from .cms_config import SnippetCMSAppConfig from .models import Snippet from .views import SnippetPreviewView @@ -16,7 +17,18 @@ djangocms_versioning_installed = False -class AbstractSnippetAdmin(admin.ModelAdmin): +djangocms_versioning_enabled = SnippetCMSAppConfig.djangocms_versioning_enabled + +snippet_admin_classes = [ + admin.ModelAdmin, +] + + +if djangocms_versioning_installed and djangocms_versioning_enabled: + snippet_admin_classes = [ExtendedVersionAdminMixin] + snippet_admin_classes + + +class SnippetAdmin(*snippet_admin_classes): list_display = ('slug', 'name') search_fields = ['slug', 'name'] prepopulated_fields = {'slug': ('name',)} @@ -31,25 +43,6 @@ class AbstractSnippetAdmin(admin.ModelAdmin): formfield_overrides = { models.TextField: {'widget': Textarea(attrs=text_area_attrs)} } - - class Meta: - abstract = True - - -djangocms_versioning_enabled = getattr( - settings, 'DJANGOCMS_SNIPPET_VERSIONING_ENABLED', False -) - -snippet_admin_classes = [ - AbstractSnippetAdmin, -] - - -if djangocms_versioning_installed and djangocms_versioning_enabled: - snippet_admin_classes = [ExtendedVersionAdminMixin] + snippet_admin_classes - - -class SnippetAdmin(*snippet_admin_classes): class Meta: model = Snippet diff --git a/djangocms_snippet/forms.py b/djangocms_snippet/forms.py index 26fb6571..f4d963e7 100644 --- a/djangocms_snippet/forms.py +++ b/djangocms_snippet/forms.py @@ -1,7 +1,8 @@ from django import forms -from django.conf import settings +from django.db import transaction from django.utils.translation import ugettext_lazy as _ +from djangocms_snippet.cms_config import SnippetCMSAppConfig from djangocms_snippet.models import Snippet, SnippetGrouper @@ -11,9 +12,7 @@ except ImportError: is_versioning_installed = False -djangocms_versioning_enabled = getattr( - settings, 'DJANGOCMS_SNIPPET_VERSIONING_ENABLED', False - ) +djangocms_versioning_enabled = SnippetCMSAppConfig.djangocms_versioning_enabled class SnippetForm(forms.ModelForm): @@ -35,13 +34,13 @@ def clean(self): name = data.get("name") slug = data.get("slug") snippet_grouper = data.get("snippet_grouper") - published_snippet_queryset = Snippet.objects.all() + snippet_queryset = Snippet.objects.all() if djangocms_versioning_enabled and is_versioning_installed: if snippet_grouper: - published_snippet_queryset.exclude(snippet_grouper=snippet_grouper) + snippet_queryset.exclude(snippet_grouper=snippet_grouper) - for snippet in published_snippet_queryset: + for snippet in snippet_queryset: if snippet.name == name: self.add_error( "name", _("A Snippet with this name already exists") @@ -53,6 +52,7 @@ def clean(self): return data + @transaction.atomic def save(self, **kwargs): if not self.cleaned_data.get("snippet_grouper"): super().save(commit=False) diff --git a/djangocms_snippet/urls.py b/djangocms_snippet/urls.py deleted file mode 100644 index 2581523c..00000000 --- a/djangocms_snippet/urls.py +++ /dev/null @@ -1,13 +0,0 @@ -from django.conf.urls import url - -from djangocms_snippet.models import Snippet -from djangocms_snippet.views import SnippetPreviewView - - -urlpatterns = [ - url( - r"^(?P\d+)/preview/$", - SnippetPreviewView.as_view(), - name=f"{Snippet._meta.app_label}_{Snippet._meta.model_name}_preview" - ) -] diff --git a/tests/test_admin.py b/tests/test_admin.py index 662b474f..eee055fa 100644 --- a/tests/test_admin.py +++ b/tests/test_admin.py @@ -6,6 +6,7 @@ from cms.test_utils.testcases import CMSTestCase from djangocms_snippet import admin as snippet_admin +from djangocms_snippet import cms_config from djangocms_snippet.models import Snippet from .utils.factories import SnippetWithVersionFactory @@ -23,12 +24,13 @@ def test_admin_list_display_without_versioning(self): Without versioning enabled, list_display should not be extended with version related items """ admin.site.unregister(Snippet) + reload(cms_config) reload(snippet_admin) self.snippet_admin = snippet_admin.SnippetAdmin(Snippet, admin) list_display = self.snippet_admin.get_list_display(self.snippet_admin_request) - self.assertEqual(self.snippet_admin.__class__.__bases__, (snippet_admin.AbstractSnippetAdmin,)) + self.assertEqual(self.snippet_admin.__class__.__bases__, (admin.ModelAdmin, )) self.assertEqual(list_display, ('slug', 'name')) def test_admin_list_display_with_versioning(self): @@ -40,7 +42,7 @@ def test_admin_list_display_with_versioning(self): list_display = self.snippet_admin.get_list_display(self.snippet_admin_request) self.assertEqual( - self.snippet_admin.__class__.__bases__, (ExtendedVersionAdminMixin, snippet_admin.AbstractSnippetAdmin) + self.snippet_admin.__class__.__bases__, (ExtendedVersionAdminMixin, admin.ModelAdmin) ) self.assertEqual( list_display[:-1], ('slug', 'name', 'get_author', 'get_modified_date', 'get_versioning_state') From 7dea453a6c638a2170f1d6949a13842b2154717e Mon Sep 17 00:00:00 2001 From: Adam Murray Date: Tue, 12 Oct 2021 11:29:06 +0100 Subject: [PATCH 100/107] Linting --- djangocms_snippet/admin.py | 1 + djangocms_snippet/views.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/djangocms_snippet/admin.py b/djangocms_snippet/admin.py index 1c8b3a86..05faf618 100644 --- a/djangocms_snippet/admin.py +++ b/djangocms_snippet/admin.py @@ -43,6 +43,7 @@ class SnippetAdmin(*snippet_admin_classes): formfield_overrides = { models.TextField: {'widget': Textarea(attrs=text_area_attrs)} } + class Meta: model = Snippet diff --git a/djangocms_snippet/views.py b/djangocms_snippet/views.py index 3b406d99..26edbe5f 100644 --- a/djangocms_snippet/views.py +++ b/djangocms_snippet/views.py @@ -10,7 +10,7 @@ class SnippetPreviewView(TemplateView): def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) snippet_id = kwargs.get("snippet_id", None) - + if not snippet_id: Http404("snippet_id must be provided.") From 75708294ccf6f9eed4ffdda16901dae76438604e Mon Sep 17 00:00:00 2001 From: Adam Murray Date: Wed, 13 Oct 2021 08:28:21 +0100 Subject: [PATCH 101/107] Clean up admin class extension Co-authored-by: Aiky30 --- djangocms_snippet/admin.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/djangocms_snippet/admin.py b/djangocms_snippet/admin.py index 05faf618..b5216800 100644 --- a/djangocms_snippet/admin.py +++ b/djangocms_snippet/admin.py @@ -9,9 +9,20 @@ from .views import SnippetPreviewView + +# Use the version mixin if djangocms-versioning is installed and enabled +snippet_admin_classes = [admin.ModelAdmin] + try: from djangocms_versioning.admin import ExtendedVersionAdminMixin + if SnippetCMSAppConfig.djangocms_versioning_enabled: + snippet_admin_classes += [ExtendedVersionAdminMixin] +except ImportError: + pass + + from djangocms_versioning.admin import ExtendedVersionAdminMixin + djangocms_versioning_installed = True except ImportError: djangocms_versioning_installed = False From 6cb31efec7f069cef7908c44d7827ac37842451b Mon Sep 17 00:00:00 2001 From: Adam Murray Date: Wed, 13 Oct 2021 18:07:14 +0100 Subject: [PATCH 102/107] PR updates --- djangocms_snippet/admin.py | 23 +++-------------------- djangocms_snippet/cms_config.py | 4 ++-- djangocms_snippet/forms.py | 2 +- djangocms_snippet/models.py | 14 +++++++++----- tests/settings.py | 3 +++ tests/test_admin.py | 2 ++ tests/test_forms.py | 30 ++++++++++++++++++++++++++++++ tests/test_models.py | 2 +- tests/test_views.py | 2 ++ 9 files changed, 53 insertions(+), 29 deletions(-) diff --git a/djangocms_snippet/admin.py b/djangocms_snippet/admin.py index b5216800..48e02314 100644 --- a/djangocms_snippet/admin.py +++ b/djangocms_snippet/admin.py @@ -9,34 +9,17 @@ from .views import SnippetPreviewView - # Use the version mixin if djangocms-versioning is installed and enabled snippet_admin_classes = [admin.ModelAdmin] +djangocms_versioning_enabled = SnippetCMSAppConfig.djangocms_versioning_enabled try: from djangocms_versioning.admin import ExtendedVersionAdminMixin - if SnippetCMSAppConfig.djangocms_versioning_enabled: - snippet_admin_classes += [ExtendedVersionAdminMixin] + if djangocms_versioning_enabled: + snippet_admin_classes.insert(0, ExtendedVersionAdminMixin) except ImportError: pass - - from djangocms_versioning.admin import ExtendedVersionAdminMixin - - djangocms_versioning_installed = True -except ImportError: - djangocms_versioning_installed = False - - -djangocms_versioning_enabled = SnippetCMSAppConfig.djangocms_versioning_enabled - -snippet_admin_classes = [ - admin.ModelAdmin, -] - - -if djangocms_versioning_installed and djangocms_versioning_enabled: - snippet_admin_classes = [ExtendedVersionAdminMixin] + snippet_admin_classes class SnippetAdmin(*snippet_admin_classes): diff --git a/djangocms_snippet/cms_config.py b/djangocms_snippet/cms_config.py index a1b6c44d..31be32c1 100644 --- a/djangocms_snippet/cms_config.py +++ b/djangocms_snippet/cms_config.py @@ -16,10 +16,10 @@ class SnippetCMSAppConfig(CMSAppConfig): djangocms_versioning_enabled = getattr( - settings, 'DJANGOCMS_SNIPPET_VERSIONING_ENABLED', False + settings, 'DJANGOCMS_SNIPPET_VERSIONING_ENABLED', True ) djangocms_moderation_enabled = getattr( - settings, 'DJANGOCMS_SNIPPET_MODERATION_ENABLED', False + settings, 'DJANGOCMS_SNIPPET_MODERATION_ENABLED', True ) cms_enabled = True diff --git a/djangocms_snippet/forms.py b/djangocms_snippet/forms.py index f4d963e7..8798c362 100644 --- a/djangocms_snippet/forms.py +++ b/djangocms_snippet/forms.py @@ -38,7 +38,7 @@ def clean(self): if djangocms_versioning_enabled and is_versioning_installed: if snippet_grouper: - snippet_queryset.exclude(snippet_grouper=snippet_grouper) + snippet_queryset = snippet_queryset.exclude(snippet_grouper=snippet_grouper) for snippet in snippet_queryset: if snippet.name == name: diff --git a/djangocms_snippet/models.py b/djangocms_snippet/models.py index c774cc7f..f73bfe5c 100644 --- a/djangocms_snippet/models.py +++ b/djangocms_snippet/models.py @@ -11,7 +11,15 @@ class SnippetGrouper(models.Model): - pass + @property + def name(self): + snippet_qs = Snippet._base_manager.filter( + snippet_grouper=self + ) + return snippet_qs.last().name or super().__str__ + + def __str__(self): + return self.name # Stores the actual data @@ -91,7 +99,3 @@ class Meta: @property def snippet(self): return self.snippet_grouper.snippet_set.first() - - def __str__(self): - # Return the referenced snippet's name rather than the default (ID #) - return self.snippet.name diff --git a/tests/settings.py b/tests/settings.py index 67f86952..60b52c6d 100644 --- a/tests/settings.py +++ b/tests/settings.py @@ -15,6 +15,9 @@ 'ALLOWED_HOSTS': ['localhost'], 'DJANGOCMS_SNIPPET_VERSIONING_ENABLED': True, 'DJANGOCMS_SNIPPET_MODERATION_ENABLED': True, + 'CMS_TEMPLATES': ( + ("page.html", "Normal page"), + ), } diff --git a/tests/test_admin.py b/tests/test_admin.py index eee055fa..0aced601 100644 --- a/tests/test_admin.py +++ b/tests/test_admin.py @@ -33,6 +33,7 @@ def test_admin_list_display_without_versioning(self): self.assertEqual(self.snippet_admin.__class__.__bases__, (admin.ModelAdmin, )) self.assertEqual(list_display, ('slug', 'name')) + @override_settings(DJANGOCMS_SNIPPET_VERSIONING_ENABLED=True) def test_admin_list_display_with_versioning(self): """ With versioning enabled, list_display should be populated with both versioning related items, and the @@ -41,6 +42,7 @@ def test_admin_list_display_with_versioning(self): from djangocms_versioning.admin import ExtendedVersionAdminMixin list_display = self.snippet_admin.get_list_display(self.snippet_admin_request) + # Mixins should always come first in the class bases self.assertEqual( self.snippet_admin.__class__.__bases__, (ExtendedVersionAdminMixin, admin.ModelAdmin) ) diff --git a/tests/test_forms.py b/tests/test_forms.py index 98e4a1e6..286af122 100644 --- a/tests/test_forms.py +++ b/tests/test_forms.py @@ -5,6 +5,8 @@ from djangocms_snippet.forms import SnippetForm from djangocms_snippet.models import Snippet, SnippetGrouper +from .utils.factories import SnippetWithVersionFactory + class SnippetFormTestCase(CMSTestCase): @@ -27,7 +29,9 @@ def test_snippet_form_creates_grouper_no_versioning(self): form.save() self.assertEqual(SnippetGrouper.objects.count(), 1) + self.assertEqual(Snippet._base_manager.count(), 1) + @override_settings(DJANGOCMS_SNIPPET_VERSIONING_ENABLED=True) def test_snippet_form_creates_grouper_with_versioning(self): """ With versioning enabled, groupers should also be created in the background. @@ -45,7 +49,9 @@ def test_snippet_form_creates_grouper_with_versioning(self): form.save() self.assertEqual(SnippetGrouper.objects.count(), 1) + self.assertEqual(Snippet._base_manager.count(), 1) + @override_settings(DJANGOCMS_SNIPPET_VERSIONING_ENABLED=True) def test_snippet_form_adds_to_existing_grouper_with_versioning(self): """ With versioning enabled, if a grouper already exists, a new one shouldn't be created @@ -66,6 +72,7 @@ def test_snippet_form_adds_to_existing_grouper_with_versioning(self): form.save() self.assertEqual(SnippetGrouper.objects.count(), 1) + self.assertEqual(Snippet._base_manager.count(), 1) form_data["html"] = "

Test Title

" @@ -77,7 +84,9 @@ def test_snippet_form_adds_to_existing_grouper_with_versioning(self): form.save() self.assertEqual(SnippetGrouper.objects.count(), 1) + self.assertEqual(Snippet._base_manager.count(), 2) + @override_settings(DJANGOCMS_SNIPPET_VERSIONING_ENABLED=True) def test_snippet_form_versioning_enabled(self): """ With versioning enabled, the snippet form doesn't have to create groupers, but does have to validate @@ -96,6 +105,7 @@ def test_snippet_form_versioning_enabled(self): form.clean() form.save() + # Publish the old created version snippet = Snippet._base_manager.last() version = snippet.versions.create(created_by=self.get_superuser()) version.publish(user=self.get_superuser()) @@ -113,3 +123,23 @@ def test_snippet_form_versioning_enabled(self): new_form.clean() self.assertDictEqual(new_form.errors, {'slug': ['A Snippet with this slug already exists']}) + + def test_snippet_form_validation_multiple_version_states_in_grouper(self): + """ + Snippet forms should be valid regardless of the versions, or states which already exist within its grouper. + """ + snippet_to_archive = SnippetWithVersionFactory() + snippet_to_archive.versions.first().publish(user=self.get_superuser()) + snippet_to_publish = SnippetWithVersionFactory(snippet_grouper=snippet_to_archive.snippet_grouper) + SnippetWithVersionFactory(snippet_grouper=snippet_to_publish.snippet_grouper) + + form_data = { + "name": snippet_to_archive.name, + "slug": snippet_to_archive.slug, + "html": "

Hello World!

", + "snippet_grouper": snippet_to_archive.snippet_grouper.id, + } + + form = SnippetForm(form_data) + + self.assertTrue(form.is_valid()) diff --git a/tests/test_models.py b/tests/test_models.py index fd3cdec6..c10f5cae 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -41,4 +41,4 @@ def test_snippet_ptr_instance(self): instance = SnippetPtr.objects.first() # test strings - self.assertEqual(str(instance), "test snippet") + self.assertEqual(instance.snippet_grouper.name, "test snippet") diff --git a/tests/test_views.py b/tests/test_views.py index ce3c7e5a..3c3c90f9 100644 --- a/tests/test_views.py +++ b/tests/test_views.py @@ -1,3 +1,5 @@ +from cms.api import add_plugin, create_page +from cms.models import PageContent from cms.test_utils.testcases import CMSTestCase from cms.utils.urlutils import admin_reverse From 9e5433f82ba37a8c102e69436121c60efadedba1 Mon Sep 17 00:00:00 2001 From: Adam Murray Date: Wed, 13 Oct 2021 18:10:22 +0100 Subject: [PATCH 103/107] Linitng --- tests/test_views.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/test_views.py b/tests/test_views.py index 3c3c90f9..ce3c7e5a 100644 --- a/tests/test_views.py +++ b/tests/test_views.py @@ -1,5 +1,3 @@ -from cms.api import add_plugin, create_page -from cms.models import PageContent from cms.test_utils.testcases import CMSTestCase from cms.utils.urlutils import admin_reverse From 68f537f3996044128ff7c9044114b46a7bf712b7 Mon Sep 17 00:00:00 2001 From: Adam Murray Date: Thu, 14 Oct 2021 11:50:05 +0100 Subject: [PATCH 104/107] Added comment to explain why cms_toolbar_models are required --- djangocms_snippet/cms_config.py | 1 + 1 file changed, 1 insertion(+) diff --git a/djangocms_snippet/cms_config.py b/djangocms_snippet/cms_config.py index 31be32c1..9d9d4629 100644 --- a/djangocms_snippet/cms_config.py +++ b/djangocms_snippet/cms_config.py @@ -23,6 +23,7 @@ class SnippetCMSAppConfig(CMSAppConfig): ) cms_enabled = True + # cms toolbar enabled to allow for versioning compare view cms_toolbar_enabled_models = [(Snippet, render_snippet), ] if djangocms_moderation_enabled and djangocms_moderation_installed: From c5dcb041f99c61b30077063d80f12c7e883fc422 Mon Sep 17 00:00:00 2001 From: Adam Murray Date: Thu, 14 Oct 2021 13:41:28 +0100 Subject: [PATCH 105/107] Update djangocms_snippet/models.py Co-authored-by: Aiky30 --- djangocms_snippet/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/djangocms_snippet/models.py b/djangocms_snippet/models.py index f73bfe5c..459cea08 100644 --- a/djangocms_snippet/models.py +++ b/djangocms_snippet/models.py @@ -16,7 +16,7 @@ def name(self): snippet_qs = Snippet._base_manager.filter( snippet_grouper=self ) - return snippet_qs.last().name or super().__str__ + return snippet_qs.first().name or super().__str__ def __str__(self): return self.name From d7e693ec82f2c8d45d44363a1059d14cada7f55c Mon Sep 17 00:00:00 2001 From: Adam Murray Date: Thu, 14 Oct 2021 14:01:24 +0100 Subject: [PATCH 106/107] Added commments to make end-to-end test clearer --- tests/test_forms.py | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/tests/test_forms.py b/tests/test_forms.py index 286af122..81af1177 100644 --- a/tests/test_forms.py +++ b/tests/test_forms.py @@ -128,10 +128,24 @@ def test_snippet_form_validation_multiple_version_states_in_grouper(self): """ Snippet forms should be valid regardless of the versions, or states which already exist within its grouper. """ + # Snippet to archive starts as draft snippet_to_archive = SnippetWithVersionFactory() + # Then it is published it snippet_to_archive.versions.first().publish(user=self.get_superuser()) - snippet_to_publish = SnippetWithVersionFactory(snippet_grouper=snippet_to_archive.snippet_grouper) - SnippetWithVersionFactory(snippet_grouper=snippet_to_publish.snippet_grouper) + # Snippet to be published starts as a draft + snippet_to_publish = SnippetWithVersionFactory( + name=snippet_to_archive.name, + slug=snippet_to_archive.slug, + snippet_grouper=snippet_to_archive.snippet_grouper + ) + # Snippet to be published is published, archiving snippet_to_archive + snippet_to_publish.versions.first().publish(user=self.get_superuser()) + # Create a new draft in the same grouper + SnippetWithVersionFactory( + name=snippet_to_archive.name, + slug=snippet_to_archive.slug, + snippet_grouper=snippet_to_archive.snippet_grouper + ) form_data = { "name": snippet_to_archive.name, From e9e3394a272952ae148018079dc5105995a2c12b Mon Sep 17 00:00:00 2001 From: Adam Murray Date: Thu, 14 Oct 2021 14:04:32 +0100 Subject: [PATCH 107/107] Comment consistency --- tests/test_forms.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/test_forms.py b/tests/test_forms.py index 81af1177..d8653d99 100644 --- a/tests/test_forms.py +++ b/tests/test_forms.py @@ -128,17 +128,17 @@ def test_snippet_form_validation_multiple_version_states_in_grouper(self): """ Snippet forms should be valid regardless of the versions, or states which already exist within its grouper. """ - # Snippet to archive starts as draft + # snippet_to_archive starts as draft snippet_to_archive = SnippetWithVersionFactory() # Then it is published it snippet_to_archive.versions.first().publish(user=self.get_superuser()) - # Snippet to be published starts as a draft + # snippet_to_publish starts as a draft snippet_to_publish = SnippetWithVersionFactory( name=snippet_to_archive.name, slug=snippet_to_archive.slug, snippet_grouper=snippet_to_archive.snippet_grouper ) - # Snippet to be published is published, archiving snippet_to_archive + # Snippet_to_publish is published, archiving snippet_to_archive snippet_to_publish.versions.first().publish(user=self.get_superuser()) # Create a new draft in the same grouper SnippetWithVersionFactory(