diff --git a/cms/test_utils/project/pluginapp/plugins/manytomany_rel/cms_plugins.py b/cms/test_utils/project/pluginapp/plugins/manytomany_rel/cms_plugins.py index c5269839738..74d3653d8cb 100644 --- a/cms/test_utils/project/pluginapp/plugins/manytomany_rel/cms_plugins.py +++ b/cms/test_utils/project/pluginapp/plugins/manytomany_rel/cms_plugins.py @@ -3,7 +3,15 @@ from cms.plugin_base import CMSPluginBase from cms.plugin_pool import plugin_pool -from cms.test_utils.project.pluginapp.plugins.manytomany_rel.models import ArticlePluginModel, Article +from cms.test_utils.project.pluginapp.plugins.manytomany_rel.models import ( + ArticlePluginModel, Article, + PluginModelWithFKFromModel, + PluginModelWithM2MToModel, + FKPluginModel, + M2MTargetPluginModel, + PluginModelWithFKFromPlugin, + PluginModelWithM2MToPlugin, +) class ArticlePlugin(CMSPluginBase): @@ -41,3 +49,48 @@ def render(self, context, instance, placeholder): return context plugin_pool.register_plugin(ArticleDynamicTemplatePlugin) + + +### + + +class PluginWithFKFromModel(CMSPluginBase): + model = PluginModelWithFKFromModel + render_template = "articles.html" + +plugin_pool.register_plugin(PluginWithFKFromModel) + + +class PluginWithM2MToModel(CMSPluginBase): + model = PluginModelWithM2MToModel + render_template = "articles.html" + +plugin_pool.register_plugin(PluginWithM2MToModel) + + +class FKPlugin(CMSPluginBase): + model = FKPluginModel + render_template = "articles.html" + +plugin_pool.register_plugin(FKPlugin) + + +class M2MTargetPlugin(CMSPluginBase): + model = M2MTargetPluginModel + render_template = "articles.html" + +plugin_pool.register_plugin(M2MTargetPlugin) + + +class PluginWithFKFromPlugin(CMSPluginBase): + model = PluginModelWithFKFromPlugin + render_template = "articles.html" + +plugin_pool.register_plugin(PluginWithFKFromPlugin) + + +class PluginWithM2MToPlugin(CMSPluginBase): + model = PluginModelWithM2MToPlugin + render_template = "articles.html" + +plugin_pool.register_plugin(PluginWithM2MToPlugin) diff --git a/cms/test_utils/project/pluginapp/plugins/manytomany_rel/migrations/0002_auto_20150601_2341.py b/cms/test_utils/project/pluginapp/plugins/manytomany_rel/migrations/0002_auto_20150601_2341.py new file mode 100644 index 00000000000..9c589c4533f --- /dev/null +++ b/cms/test_utils/project/pluginapp/plugins/manytomany_rel/migrations/0002_auto_20150601_2341.py @@ -0,0 +1,111 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import models, migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('cms', '0011_auto_20150419_1006'), + ('manytomany_rel', '0001_initial'), + ] + + operations = [ + migrations.CreateModel( + name='FKModel', + fields=[ + ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), + ], + options={ + }, + bases=(models.Model,), + ), + migrations.CreateModel( + name='FKPluginModel', + fields=[ + ('cmsplugin_ptr', models.OneToOneField(parent_link=True, auto_created=True, primary_key=True, serialize=False, to='cms.CMSPlugin')), + ], + options={ + 'abstract': False, + }, + bases=('cms.cmsplugin',), + ), + migrations.CreateModel( + name='M2MTargetModel', + fields=[ + ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), + ('title', models.CharField(max_length=50)), + ], + options={ + }, + bases=(models.Model,), + ), + migrations.CreateModel( + name='M2MTargetPluginModel', + fields=[ + ('cmsplugin_ptr', models.OneToOneField(parent_link=True, auto_created=True, primary_key=True, serialize=False, to='cms.CMSPlugin')), + ('title', models.CharField(max_length=50)), + ], + options={ + 'abstract': False, + }, + bases=('cms.cmsplugin',), + ), + migrations.CreateModel( + name='PluginModelWithFKFromModel', + fields=[ + ('cmsplugin_ptr', models.OneToOneField(parent_link=True, auto_created=True, primary_key=True, serialize=False, to='cms.CMSPlugin')), + ('title', models.CharField(max_length=50)), + ], + options={ + 'abstract': False, + }, + bases=('cms.cmsplugin',), + ), + migrations.CreateModel( + name='PluginModelWithFKFromPlugin', + fields=[ + ('cmsplugin_ptr', models.OneToOneField(parent_link=True, auto_created=True, primary_key=True, serialize=False, to='cms.CMSPlugin')), + ('title', models.CharField(max_length=50)), + ], + options={ + 'abstract': False, + }, + bases=('cms.cmsplugin',), + ), + migrations.CreateModel( + name='PluginModelWithM2MToModel', + fields=[ + ('cmsplugin_ptr', models.OneToOneField(parent_link=True, auto_created=True, primary_key=True, serialize=False, to='cms.CMSPlugin')), + ('m2m_field', models.ManyToManyField(to='manytomany_rel.M2MTargetModel')), + ], + options={ + 'abstract': False, + }, + bases=('cms.cmsplugin',), + ), + migrations.CreateModel( + name='PluginModelWithM2MToPlugin', + fields=[ + ('cmsplugin_ptr', models.OneToOneField(parent_link=True, auto_created=True, primary_key=True, serialize=False, to='cms.CMSPlugin')), + ('m2m_field', models.ManyToManyField(to='manytomany_rel.M2MTargetPluginModel')), + ], + options={ + 'abstract': False, + }, + bases=('cms.cmsplugin',), + ), + migrations.AddField( + model_name='fkpluginmodel', + name='fk_field', + field=models.ForeignKey(to='manytomany_rel.PluginModelWithFKFromPlugin'), + preserve_default=True, + ), + migrations.AddField( + model_name='fkmodel', + name='fk_field', + field=models.ForeignKey(to='manytomany_rel.PluginModelWithFKFromModel'), + preserve_default=True, + ), + ] diff --git a/cms/test_utils/project/pluginapp/plugins/manytomany_rel/models.py b/cms/test_utils/project/pluginapp/plugins/manytomany_rel/models.py index 9e88a872cc3..2586b5d005c 100644 --- a/cms/test_utils/project/pluginapp/plugins/manytomany_rel/models.py +++ b/cms/test_utils/project/pluginapp/plugins/manytomany_rel/models.py @@ -31,3 +31,60 @@ def __str__(self): def copy_relations(self, oldinstance): self.sections = oldinstance.sections.all() + + +### + + +class FKModel(models.Model): + fk_field = models.ForeignKey('PluginModelWithFKFromModel') + + +class M2MTargetModel(models.Model): + title = models.CharField(max_length=50) + + +class PluginModelWithFKFromModel(CMSPlugin): + title = models.CharField(max_length=50) + + def copy_relations(self, oldinstance): + # Like suggested in the docs + for associated_item in oldinstance.fkmodel_set.all(): + associated_item.pk = None + associated_item.fk_field = self + associated_item.save() + + +class PluginModelWithM2MToModel(CMSPlugin): + m2m_field = models.ManyToManyField(M2MTargetModel) + + def copy_relations(self, oldinstance): + # Like suggested in the docs + self.m2m_field = oldinstance.m2m_field.all() + + +class FKPluginModel(CMSPlugin): + fk_field = models.ForeignKey('PluginModelWithFKFromPlugin') + + +class M2MTargetPluginModel(CMSPlugin): + title = models.CharField(max_length=50) + + +class PluginModelWithFKFromPlugin(CMSPlugin): + title = models.CharField(max_length=50) + + def copy_relations(self, oldinstance): + # Like suggested in the docs + for associated_item in oldinstance.fkpluginmodel_set.all(): + associated_item.pk = None + associated_item.fk_field = self + associated_item.save() + + +class PluginModelWithM2MToPlugin(CMSPlugin): + m2m_field = models.ManyToManyField(M2MTargetPluginModel) + + def copy_relations(self, oldinstance): + # Like suggested in the docs + self.m2m_field = oldinstance.m2m_field.all() diff --git a/cms/tests/plugins.py b/cms/tests/plugins.py index 7cb7015f92d..e2ee4de1ed2 100644 --- a/cms/tests/plugins.py +++ b/cms/tests/plugins.py @@ -8,6 +8,7 @@ from django.conf import settings from django.conf.urls import url from django.contrib import admin +from django.contrib.auth.models import User from django.core import urlresolvers from django.core.cache import cache from django.core.exceptions import ValidationError, ImproperlyConfigured @@ -26,7 +27,11 @@ from cms.plugin_pool import plugin_pool from cms.sitemaps.cms_sitemap import CMSSitemap from cms.test_utils.project.pluginapp.plugins.manytomany_rel.models import ( - Article, Section, ArticlePluginModel) + Article, Section, ArticlePluginModel, + FKModel, + M2MTargetModel, + FKPluginModel, + PluginModelWithM2MToPlugin,) from cms.test_utils.project.pluginapp.plugins.meta.cms_plugins import ( TestPlugin, TestPlugin2, TestPlugin3, TestPlugin4, TestPlugin5) from cms.test_utils.project.pluginapp.plugins.validation.cms_plugins import ( @@ -1472,6 +1477,140 @@ def test_copy_plugin_with_m2m(self): self.assertEqual(expected, db_counts) +class PluginCopyRelationsTestCase(PluginsTestBaseCase): + """Test the suggestions in the docs for copy_relations()""" + + def setUp(self): + self.super_user = self._create_user("test", True, True) + self.FIRST_LANG = settings.LANGUAGES[0][0] + page_data1 = self.get_new_page_data_dbfields() + page_data1['published'] = False + self.page1 = api.create_page(**page_data1) + page_data2 = self.get_new_page_data_dbfields() + page_data2['published'] = False + self.page2 = api.create_page(**page_data2) + self.placeholder1 = self.page1.placeholders.get(slot='body') + self.placeholder2 = self.page2.placeholders.get(slot='body') + + def tearDown(self): + User.objects.all().delete() + Page.objects.all().delete() + + def test_copy_fk_from_model(self): + plugin = api.add_plugin( + placeholder=self.placeholder1, + plugin_type="PluginWithFKFromModel", + language=self.FIRST_LANG, + ) + FKModel.objects.create(fk_field=plugin) + old_public_count = FKModel.objects.filter( + fk_field__placeholder__page__publisher_is_draft=False + ).count() + api.publish_page( + self.page1, + self.super_user, + self.FIRST_LANG + ) + new_public_count = FKModel.objects.filter( + fk_field__placeholder__page__publisher_is_draft=False + ).count() + self.assertEqual( + new_public_count, + old_public_count + 1 + ) + + def test_copy_m2m_to_model(self): + plugin = api.add_plugin( + placeholder=self.placeholder1, + plugin_type="PluginWithM2MToModel", + language=self.FIRST_LANG, + ) + m2m_target = M2MTargetModel.objects.create() + plugin.m2m_field.add(m2m_target) + old_public_count = M2MTargetModel.objects.filter( + pluginmodelwithm2mtomodel__placeholder__page__publisher_is_draft=False + ).count() + api.publish_page( + self.page1, + self.super_user, + self.FIRST_LANG + ) + new_public_count = M2MTargetModel.objects.filter( + pluginmodelwithm2mtomodel__placeholder__page__publisher_is_draft=False + ).count() + self.assertEqual( + new_public_count, + old_public_count + 1 + ) + + def test_copy_fk_from_plugin(self): + plugin = api.add_plugin( + placeholder=self.placeholder1, + plugin_type="PluginWithFKFromPlugin", + language=self.FIRST_LANG, + ) + api.add_plugin( + placeholder=self.placeholder2, + plugin_type='FKPlugin', + language=self.FIRST_LANG, + fk_field=plugin + ) + old_plugin_count = FKPluginModel.objects.filter( + fk_field__placeholder__page__publisher_is_draft=False + ).count() + api.publish_page( + self.page1, + self.super_user, + self.FIRST_LANG + ) + api.publish_page( + self.page2, + self.super_user, + self.FIRST_LANG + ) + new_plugin_count = FKPluginModel.objects.filter( + fk_field__placeholder__page__publisher_is_draft=False + ).count() + self.assertEqual( + new_plugin_count, + old_plugin_count + 1 + ) + + def test_copy_m2m_to_plugin(self): + plugin = api.add_plugin( + placeholder=self.placeholder1, + plugin_type="PluginWithM2MToPlugin", + language=self.FIRST_LANG, + ) + m2m_target = api.add_plugin( + placeholder=self.placeholder2, + plugin_type='M2MTargetPlugin', + language=self.FIRST_LANG + ) + plugin.m2m_field.add(m2m_target) + old_public_count = PluginModelWithM2MToPlugin.objects.filter( + m2m_field__placeholder__page__publisher_is_draft=False + ).count() + api.publish_page( + self.page1, + self.super_user, + self.FIRST_LANG + ) + api.publish_page( + self.page2, + self.super_user, + self.FIRST_LANG + ) + new_public_count = PluginModelWithM2MToPlugin.objects.filter( + m2m_field__placeholder__page__publisher_is_draft=False + ).count() + self.assertEqual( + new_public_count, + old_public_count + 1 + ) + + + class PluginsMetaOptionsTests(TestCase): ''' TestCase set for ensuring that bugs like #992 are caught '''