diff --git a/localized_fields/fields/localized_uniqueslug_field.py b/localized_fields/fields/localized_uniqueslug_field.py index bcbabb6..a5ac993 100644 --- a/localized_fields/fields/localized_uniqueslug_field.py +++ b/localized_fields/fields/localized_uniqueslug_field.py @@ -1,3 +1,5 @@ +from datetime import datetime + from django.conf import settings from django.utils.text import slugify from django.core.exceptions import ImproperlyConfigured @@ -7,8 +9,6 @@ from ..mixins import AtomicSlugRetryMixin from ..localized_value import LocalizedValue from .localized_autoslug_field import LocalizedAutoSlugField -from datetime import datetime - class LocalizedUniqueSlugField(LocalizedAutoSlugField): """Automatically provides slugs for a localized @@ -47,8 +47,6 @@ class LocalizedUniqueSlugField(LocalizedAutoSlugField): kwargs['populate_from'] = self.populate_from kwargs['include_time'] = self.include_time - # if not kwargs['include_time']: - # raise RuntimeError() return name, path, args, kwargs def pre_save(self, instance, add: bool): @@ -86,11 +84,25 @@ class LocalizedUniqueSlugField(LocalizedAutoSlugField): continue slug = slugify(value, allow_unicode=True) + + # verify whether it's needed to re-generate a slug, + # if not, re-use the same slug + if instance.pk is not None: + current_slug = getattr(instance, self.name).get(lang_code) + if current_slug is not None: + stripped_slug = current_slug[0:current_slug.rfind('-')] + if slug == stripped_slug: + slugs.set(lang_code, current_slug) + continue + if self.include_time: slug += '-%d' % datetime.now().microsecond if instance.retries > 0: - slug += '-%d' % instance.retries + # do not add another - if we already added time + if not self.include_time: + slug += '-' + slug += '%d' % instance.retries slugs.set(lang_code, slug) diff --git a/tests/test_localized_slug_fields.py b/tests/test_localized_slug_fields.py index 5455369..51fac26 100644 --- a/tests/test_localized_slug_fields.py +++ b/tests/test_localized_slug_fields.py @@ -1,11 +1,12 @@ +import copy + from django import forms from django.conf import settings from django.test import TestCase from django.db.utils import IntegrityError -from django.utils.text import slugify - from localized_fields import (LocalizedField, LocalizedAutoSlugField, LocalizedUniqueSlugField) +from django.utils.text import slugify from .fake_model import get_fake_model @@ -83,6 +84,33 @@ class LocalizedSlugFieldTestCase(TestCase): assert obj.slug.en.startswith('%s-' % title) + @classmethod + def test_uniue_slug_no_change(cls): + """Tests whether slugs are not re-generated if not needed.""" + + NoChangeSlugModel = get_fake_model( + 'NoChangeSlugModel', + { + 'title': LocalizedField(), + 'slug': LocalizedUniqueSlugField(populate_from='title', include_time=True) + } + ) + + title = 'myuniquetitle' + + obj = NoChangeSlugModel() + obj.title.en = title + obj.title.nl = title + obj.save() + + old_slug_en = copy.deepcopy(obj.slug.en) + old_slug_nl = copy.deepcopy(obj.slug.nl) + obj.title.nl += 'beer' + obj.save() + + assert old_slug_en == obj.slug.en + assert old_slug_nl != obj.slug.nl + def test_unique_slug_unique_max_retries(self): """Tests whether the unique slug implementation doesn't try to find a slug forever and gives up after a while."""