From afb94ecf6625e5976b526d77dd570a54452e62f5 Mon Sep 17 00:00:00 2001 From: Swen Kooij Date: Fri, 27 Nov 2020 16:35:33 +0200 Subject: [PATCH] Add a flag to make LocalizedUniqueSlugField immutable --- localized_fields/fields/uniqueslug_field.py | 16 ++++++++++++- tests/test_slug_fields.py | 26 +++++++++++++++++++++ 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/localized_fields/fields/uniqueslug_field.py b/localized_fields/fields/uniqueslug_field.py index 23e3fdb..e87c6e2 100644 --- a/localized_fields/fields/uniqueslug_field.py +++ b/localized_fields/fields/uniqueslug_field.py @@ -21,6 +21,10 @@ class LocalizedUniqueSlugField(LocalizedAutoSlugField): When in doubt, use this over :see:LocalizedAutoSlugField. Inherit from :see:AtomicSlugRetryMixin in your model to make this field work properly. + + By default, this creates a new slug if the field(s) specified + in `populate_from` are changed. Set `immutable=True` to get + immutable slugs. """ def __init__(self, *args, **kwargs): @@ -28,6 +32,8 @@ def __init__(self, *args, **kwargs): kwargs["uniqueness"] = kwargs.pop("uniqueness", get_language_codes()) + self.immutable = kwargs.pop("immutable", False) + super(LocalizedUniqueSlugField, self).__init__(*args, **kwargs) self.populate_from = kwargs.pop("populate_from") @@ -42,6 +48,10 @@ def deconstruct(self): kwargs["populate_from"] = self.populate_from kwargs["include_time"] = self.include_time + + if self.immutable is True: + kwargs["immutable"] = self.immutable + return name, path, args, kwargs def pre_save(self, instance, add: bool): @@ -76,10 +86,14 @@ def pre_save(self, instance, add: bool): slug = slugify(value, allow_unicode=True) + current_slug = getattr(instance, self.name).get(lang_code) + if current_slug and self.immutable: + slugs.set(lang_code, current_slug) + continue + # 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: current_slug_end_index = current_slug.rfind("-") stripped_slug = current_slug[0:current_slug_end_index] diff --git a/tests/test_slug_fields.py b/tests/test_slug_fields.py index d3da9d0..936ffe3 100644 --- a/tests/test_slug_fields.py +++ b/tests/test_slug_fields.py @@ -215,6 +215,32 @@ def test_populate_multiple_languages(cls): for lang_code, lang_name in settings.LANGUAGES: assert obj.slug.get(lang_code) == "title-%s" % lang_name.lower() + @classmethod + def test_allows_override_when_immutable(cls): + """Tests whether setting a value manually works and does not get + overriden.""" + + Model = get_fake_model( + { + "title": LocalizedField(), + "name": models.CharField(max_length=255), + "slug": LocalizedUniqueSlugField( + populate_from="title", immutable=True + ), + } + ) + + obj = Model() + + for lang_code, lang_name in settings.LANGUAGES: + obj.slug.set(lang_code, "my value %s" % lang_code) + obj.title.set(lang_code, "my title %s" % lang_code) + + obj.save() + + for lang_code, lang_name in settings.LANGUAGES: + assert obj.slug.get(lang_code) == "my value %s" % lang_code + @classmethod def test_unique_slug(cls): """Tests whether unique slugs are properly generated."""