Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a flag to make LocalizedUniqueSlugField immutable #91

Merged
merged 1 commit into from Nov 30, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
16 changes: 15 additions & 1 deletion localized_fields/fields/uniqueslug_field.py
Expand Up @@ -21,13 +21,19 @@ 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):
"""Initializes a new instance of :see:LocalizedUniqueSlugField."""

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")
Expand All @@ -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):
Expand Down Expand Up @@ -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]
Expand Down
26 changes: 26 additions & 0 deletions tests/test_slug_fields.py
Expand Up @@ -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."""
Expand Down