Skip to content

Commit a441d5a

Browse files
authored
feat: Snippet CMS 4.0 and djangocms-versioning Data migration (#74)
1 parent eeb8072 commit a441d5a

13 files changed

+352
-56
lines changed

README.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,11 @@ please set ``DJANGOCMS_SNIPPET_CACHE`` to ``False`` in your settings::
8080

8181
DJANGOCMS_SNIPPET_CACHE = False # default value is True
8282

83+
Migration 0010 requires the use of a user in order to create versions for existing snippets (if djangocms_versioning is installed and enabled),
84+
a user can be chosen with the setting ``DJANGOCMS_SNIPPET_VERSIONING_MIGRATION_USER_ID``, the default is 1.
85+
86+
DJANGOCMS_SNIPPET_VERSIONING_MIGRATION_USER_ID = 2 # Will use user with id: 2
87+
8388
Template tag
8489
------------
8590

djangocms_snippet/conf.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
from django.conf import settings
2+
3+
4+
DJANGOCMS_SNIPPET_VERSIONING_MIGRATION_USER_ID = getattr(
5+
settings, "DJANGOCMS_SNIPPET_VERSIONING_MIGRATION_USER_ID", 1
6+
)

djangocms_snippet/migrations/0009_auto_20210811_0942.py renamed to djangocms_snippet/migrations/0009_auto_20210915_0445.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Generated by Django 2.2.24 on 2021-08-11 09:42
1+
# Generated by Django 2.2.24 on 2021-09-15 04:45
22

33
import django.db.models.deletion
44
from django.db import migrations, models
@@ -20,6 +20,11 @@ class Migration(migrations.Migration):
2020
migrations.AddField(
2121
model_name='snippet',
2222
name='snippet_grouper',
23-
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, to='djangocms_snippet.SnippetGrouper'),
23+
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='djangocms_snippet.SnippetGrouper'),
24+
),
25+
migrations.AddField(
26+
model_name='snippetptr',
27+
name='snippet_grouper',
28+
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='djangocms_snippet.SnippetGrouper'),
2429
),
2530
]
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
from django.apps import apps as global_apps
2+
from django.contrib.contenttypes.management import create_contenttypes
3+
from django.db import migrations
4+
5+
from djangocms_snippet.cms_config import SnippetCMSAppConfig
6+
from djangocms_snippet.conf import (
7+
DJANGOCMS_SNIPPET_VERSIONING_MIGRATION_USER_ID,
8+
)
9+
10+
11+
try:
12+
from djangocms_versioning.constants import DRAFT
13+
14+
djangocms_versioning_installed = True
15+
except ImportError:
16+
djangocms_versioning_installed = False
17+
18+
19+
def cms4_grouper_version_migration(apps, schema_editor):
20+
create_contenttypes(global_apps.get_app_config("djangocms_snippet"))
21+
22+
djangocms_versioning_config_enabled = SnippetCMSAppConfig.djangocms_versioning_enabled
23+
24+
ContentType = apps.get_model('contenttypes', 'ContentType')
25+
Snippet = apps.get_model('djangocms_snippet', 'Snippet')
26+
SnippetGrouper = apps.get_model('djangocms_snippet', 'SnippetGrouper')
27+
User = apps.get_model('auth', 'User')
28+
29+
snippet_contenttype = ContentType.objects.get(app_label='djangocms_snippet', model='snippet')
30+
snippet_queryset = Snippet.objects.all()
31+
32+
for snippet in snippet_queryset:
33+
grouper = SnippetGrouper.objects.create()
34+
snippet.snippet_grouper = grouper
35+
snippet.save()
36+
37+
# Get a migration user.
38+
migration_user = User.objects.get(id=DJANGOCMS_SNIPPET_VERSIONING_MIGRATION_USER_ID)
39+
40+
# Create initial Snippet Versions if versioning is enabled and installed.
41+
if djangocms_versioning_config_enabled and djangocms_versioning_installed:
42+
Version = apps.get_model('djangocms_versioning', 'Version')
43+
Version.objects.create(
44+
created_by=migration_user,
45+
state=DRAFT,
46+
number=1,
47+
object_id=snippet.pk,
48+
content_type=snippet_contenttype,
49+
)
50+
51+
52+
class Migration(migrations.Migration):
53+
dependencies = [
54+
('cms', '0034_remove_pagecontent_placeholders'), # Run after the CMS4 migrations
55+
('djangocms_snippet', '0009_auto_20210915_0445'),
56+
]
57+
58+
if djangocms_versioning_installed:
59+
dependencies += [('djangocms_versioning', '0015_version_modified'), ]
60+
61+
operations = [
62+
migrations.RunPython(cms4_grouper_version_migration)
63+
]
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# Generated by Django 2.2.24 on 2021-08-31 10:45
2+
from django.db import migrations
3+
4+
5+
def cms4_migration(apps, schema_editor):
6+
SnippetPtr = apps.get_model('djangocms_snippet', 'SnippetPtr')
7+
8+
for snippet_plugin in SnippetPtr.objects.all():
9+
snippet = snippet_plugin.snippet
10+
snippet_plugin.snippet_grouper = snippet.snippet_grouper
11+
snippet_plugin.save()
12+
13+
14+
class Migration(migrations.Migration):
15+
16+
dependencies = [
17+
('djangocms_snippet', '0010_cms4_grouper_version_data_migration'),
18+
]
19+
20+
operations = [
21+
migrations.RunPython(cms4_migration)
22+
]
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# Generated by Django 2.2.24 on 2021-09-15 07:21
2+
3+
import django.db.models.deletion
4+
from django.db import migrations, models
5+
6+
7+
class Migration(migrations.Migration):
8+
9+
dependencies = [
10+
('djangocms_snippet', '0011_cms4_plugin_data_migration'),
11+
]
12+
13+
operations = [
14+
migrations.RemoveField(
15+
model_name='snippetptr',
16+
name='snippet',
17+
),
18+
migrations.AlterField(
19+
model_name='snippet',
20+
name='snippet_grouper',
21+
field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='djangocms_snippet.SnippetGrouper'),
22+
),
23+
migrations.AlterField(
24+
model_name='snippetptr',
25+
name='snippet_grouper',
26+
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='djangocms_snippet.SnippetGrouper'),
27+
),
28+
]

djangocms_snippet/models.py

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,12 @@ class Snippet(models.Model):
2020
"""
2121
name = models.CharField(
2222
verbose_name=_('Name'),
23-
unique=True,
2423
max_length=255,
24+
unique=True,
2525
)
2626
snippet_grouper = models.ForeignKey(
2727
SnippetGrouper,
2828
on_delete=models.PROTECT,
29-
null=True,
3029
)
3130
html = models.TextField(
3231
verbose_name=_('HTML'),
@@ -44,10 +43,10 @@ class Snippet(models.Model):
4443
)
4544
slug = models.SlugField(
4645
verbose_name=_('Slug'),
47-
unique=True,
4846
blank=False,
4947
default='',
5048
max_length=255,
49+
unique=True,
5150
)
5251

5352
def __str__(self):
@@ -71,14 +70,21 @@ class SnippetPtr(CMSPlugin):
7170
parent_link=True,
7271
on_delete=models.CASCADE,
7372
)
74-
snippet = models.ForeignKey(Snippet, on_delete=models.CASCADE)
73+
snippet_grouper = models.ForeignKey(
74+
SnippetGrouper,
75+
on_delete=models.CASCADE,
76+
)
7577

7678
search_fields = ['snippet__html'] if SEARCH_ENABLED else []
7779

7880
class Meta:
7981
verbose_name = _('Snippet Ptr')
8082
verbose_name_plural = _('Snippet Ptrs')
8183

84+
@property
85+
def snippet(self):
86+
return self.snippet_grouper.snippet_set.first()
87+
8288
def __str__(self):
8389
# Return the referenced snippet's name rather than the default (ID #)
8490
return self.snippet.name

tests/requirements/base.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,4 @@ tox
33
coverage
44
isort
55
flake8
6+
factory-boy

tests/settings.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
HELPER_SETTINGS = {
33
'INSTALLED_APPS': [
44
'tests.utils',
5+
'djangocms_versioning',
6+
'djangocms_snippet',
57
],
68
'CMS_LANGUAGES': {
79
1: [{
@@ -11,6 +13,7 @@
1113
},
1214
'LANGUAGE_CODE': 'en',
1315
'ALLOWED_HOSTS': ['localhost'],
16+
'DJANGOCMS_SNIPPET_VERSIONING_ENABLED': True,
1417
}
1518

1619

tests/test_models.py

Lines changed: 18 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,44 @@
1-
from django.test import TestCase
1+
from cms.test_utils.testcases import CMSTestCase
22

33
from djangocms_snippet.models import SEARCH_ENABLED, Snippet, SnippetPtr
44

5+
from .utils.factories import SnippetPluginFactory, SnippetWithVersionFactory
56

6-
class SnippetModelTestCase(TestCase):
77

8-
def setUp(self):
9-
pass
8+
class SnippetModelTestCase(CMSTestCase):
109

11-
def tearDown(self):
12-
pass
10+
def setUp(self):
11+
self.snippet = SnippetWithVersionFactory(
12+
name="test snippet",
13+
html="<p>hello world</p>",
14+
slug="test_snippet",
15+
)
16+
self.snippet.versions.last().publish(user=self.get_superuser())
17+
self.snippet_grouper = self.snippet.snippet_grouper
18+
SnippetPluginFactory(snippet_grouper=self.snippet_grouper, language=["en"])
1319

1420
def test_settings(self):
1521
self.assertEqual(SEARCH_ENABLED, False)
1622

1723
def test_snippet_instance(self):
18-
Snippet.objects.create(
19-
name="test snippet",
20-
html="<p>hello world</p>",
21-
slug="test_snippet",
22-
)
2324
instance = Snippet.objects.all()
25+
2426
self.assertEqual(instance.count(), 1)
27+
2528
instance = Snippet.objects.first()
29+
2630
self.assertEqual(instance.name, "test snippet")
2731
self.assertEqual(instance.html, "<p>hello world</p>")
2832
self.assertEqual(instance.slug, "test_snippet")
2933
# test strings
3034
self.assertEqual(str(instance), "test snippet")
3135

3236
def test_snippet_ptr_instance(self):
33-
snippet = Snippet.objects.create(
34-
name="test snippet",
35-
html="<p>hello world</p>",
36-
slug="test_snippet",
37-
)
38-
SnippetPtr.objects.create(
39-
snippet=snippet,
40-
)
4137
instance = SnippetPtr.objects.all()
38+
4239
self.assertEqual(instance.count(), 1)
40+
4341
instance = SnippetPtr.objects.first()
42+
4443
# test strings
4544
self.assertEqual(str(instance), "test snippet")

0 commit comments

Comments
 (0)