From b52ce9c839aabada19bf8c2c89a2505119de09c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Dlouh=C3=BD?= Date: Fri, 13 Mar 2020 15:49:35 +0100 Subject: [PATCH] make datamigration for non-unique slugs, test the migration --- .../migrations/0005_unique_category_slug.py | 20 ++++++++- categories/tests/test_migrations.py | 42 +++++++++++++++++++ tox.ini | 5 +++ 3 files changed, 66 insertions(+), 1 deletion(-) create mode 100644 categories/tests/test_migrations.py diff --git a/categories/migrations/0005_unique_category_slug.py b/categories/migrations/0005_unique_category_slug.py index e3071e9..1be7e62 100644 --- a/categories/migrations/0005_unique_category_slug.py +++ b/categories/migrations/0005_unique_category_slug.py @@ -2,14 +2,32 @@ from django.db import migrations, models +from categories.models import Category + + +def make_slugs_unique(apps, schema_editor): + duplicates = Category.tree.values("slug").annotate(slug_count=models.Count("slug")).filter(slug_count__gt=1) + category_objs = [] + for duplicate in duplicates: + slug = duplicate["slug"] + categories = Category.tree.filter(slug=slug) + count = categories.count() + i = 0 + for category in categories.all(): + if i != 0: + category.slug = "{}-{}".format(slug, str(i).zfill(len(str(count)))) + category_objs.append(category) + i += 1 + Category.objects.bulk_update(category_objs, ["slug"]) + class Migration(migrations.Migration): - dependencies = [ ("categories", "0004_auto_20200517_1832"), ] operations = [ + migrations.RunPython(make_slugs_unique, reverse_code=migrations.RunPython.noop), migrations.AlterField( model_name="category", name="slug", diff --git a/categories/tests/test_migrations.py b/categories/tests/test_migrations.py new file mode 100644 index 0000000..211955d --- /dev/null +++ b/categories/tests/test_migrations.py @@ -0,0 +1,42 @@ +import sys + +if sys.version_info >= (3, 0): + from django_test_migrations.contrib.unittest_case import MigratorTestCase + + class TestMigrations(MigratorTestCase): + migrate_from = ("categories", "0004_auto_20200517_1832") + migrate_to = ("categories", "0005_unique_category_slug") + + def prepare(self): + Category = self.old_state.apps.get_model("categories", "Category") + Category.tree.create(slug="foo", lft=0, rght=0, tree_id=0, level=0) + Category.tree.create(slug="foo", lft=0, rght=0, tree_id=0, level=0) + Category.tree.create(slug="foo", lft=0, rght=0, tree_id=0, level=0) + for i in range(1, 12): + Category.tree.create(slug="bar", lft=0, rght=0, tree_id=0, level=0) + Category.tree.create(slug="baz", lft=0, rght=0, tree_id=0, level=0) + assert Category.tree.count() == 15 + + def test_unique_slug_migration(self): + Category = self.new_state.apps.get_model("categories", "Category") + + self.assertListEqual( + list(Category.tree.values_list("slug", flat=True)), + [ + "foo", + "foo-1", + "foo-2", + "bar", + "bar-01", + "bar-02", + "bar-03", + "bar-04", + "bar-05", + "bar-06", + "bar-07", + "bar-08", + "bar-09", + "bar-10", + "baz", + ], + ) diff --git a/tox.ini b/tox.ini index f344072..6dbcb2f 100644 --- a/tox.ini +++ b/tox.ini @@ -37,6 +37,11 @@ deps= pillow ipdb codecov + django-test-migrations + django21: django-test-migrations<=1.2.0 + django22: django-test-migrations<=1.2.0 + django3: django-test-migrations<=1.2.0 + django31: django-test-migrations<=1.2.0 -r{toxinidir}/requirements.txt commands=