mirror of
https://github.com/SectorLabs/django-localized-fields.git
synced 2025-10-26 08:58:58 +03:00
Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f024e4feb5 | ||
|
|
92cb5e8b1f | ||
|
|
5c298ef13e | ||
|
|
1b3e5989d3 | ||
|
|
d57f9a41bb | ||
|
|
bd8924224e | ||
|
|
62e1e805c7 | ||
|
|
afc39745bf | ||
|
|
1406954dec | ||
|
|
afb94ecf66 |
@@ -21,6 +21,10 @@ class LocalizedUniqueSlugField(LocalizedAutoSlugField):
|
|||||||
When in doubt, use this over :see:LocalizedAutoSlugField.
|
When in doubt, use this over :see:LocalizedAutoSlugField.
|
||||||
Inherit from :see:AtomicSlugRetryMixin in your model to
|
Inherit from :see:AtomicSlugRetryMixin in your model to
|
||||||
make this field work properly.
|
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):
|
def __init__(self, *args, **kwargs):
|
||||||
@@ -28,6 +32,9 @@ class LocalizedUniqueSlugField(LocalizedAutoSlugField):
|
|||||||
|
|
||||||
kwargs["uniqueness"] = kwargs.pop("uniqueness", get_language_codes())
|
kwargs["uniqueness"] = kwargs.pop("uniqueness", get_language_codes())
|
||||||
|
|
||||||
|
self.enabled = kwargs.pop("enabled", True)
|
||||||
|
self.immutable = kwargs.pop("immutable", False)
|
||||||
|
|
||||||
super(LocalizedUniqueSlugField, self).__init__(*args, **kwargs)
|
super(LocalizedUniqueSlugField, self).__init__(*args, **kwargs)
|
||||||
|
|
||||||
self.populate_from = kwargs.pop("populate_from")
|
self.populate_from = kwargs.pop("populate_from")
|
||||||
@@ -42,6 +49,13 @@ class LocalizedUniqueSlugField(LocalizedAutoSlugField):
|
|||||||
|
|
||||||
kwargs["populate_from"] = self.populate_from
|
kwargs["populate_from"] = self.populate_from
|
||||||
kwargs["include_time"] = self.include_time
|
kwargs["include_time"] = self.include_time
|
||||||
|
|
||||||
|
if self.enabled is False:
|
||||||
|
kwargs["enabled"] = self.enabled
|
||||||
|
|
||||||
|
if self.immutable is True:
|
||||||
|
kwargs["immutable"] = self.immutable
|
||||||
|
|
||||||
return name, path, args, kwargs
|
return name, path, args, kwargs
|
||||||
|
|
||||||
def pre_save(self, instance, add: bool):
|
def pre_save(self, instance, add: bool):
|
||||||
@@ -59,6 +73,9 @@ class LocalizedUniqueSlugField(LocalizedAutoSlugField):
|
|||||||
The localized slug that was generated.
|
The localized slug that was generated.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
if not self.enabled:
|
||||||
|
return getattr(instance, self.name)
|
||||||
|
|
||||||
if not isinstance(instance, AtomicSlugRetryMixin):
|
if not isinstance(instance, AtomicSlugRetryMixin):
|
||||||
raise ImproperlyConfigured(
|
raise ImproperlyConfigured(
|
||||||
(
|
(
|
||||||
@@ -76,10 +93,14 @@ class LocalizedUniqueSlugField(LocalizedAutoSlugField):
|
|||||||
|
|
||||||
slug = slugify(value, allow_unicode=True)
|
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,
|
# verify whether it's needed to re-generate a slug,
|
||||||
# if not, re-use the same slug
|
# if not, re-use the same slug
|
||||||
if instance.pk is not None:
|
if instance.pk is not None:
|
||||||
current_slug = getattr(instance, self.name).get(lang_code)
|
|
||||||
if current_slug is not None:
|
if current_slug is not None:
|
||||||
current_slug_end_index = current_slug.rfind("-")
|
current_slug_end_index = current_slug.rfind("-")
|
||||||
stripped_slug = current_slug[0:current_slug_end_index]
|
stripped_slug = current_slug[0:current_slug_end_index]
|
||||||
|
|||||||
@@ -136,6 +136,15 @@ class LocalizedValue(dict):
|
|||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
def is_empty(self) -> bool:
|
||||||
|
"""Gets whether all the languages contain the default value."""
|
||||||
|
|
||||||
|
for lang_code, _ in settings.LANGUAGES:
|
||||||
|
if self.get(lang_code) != self.default_value:
|
||||||
|
return False
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
def __str__(self) -> str:
|
def __str__(self) -> str:
|
||||||
"""Gets the value in the current language or falls back to the next
|
"""Gets the value in the current language or falls back to the next
|
||||||
language if there's no value in the current language."""
|
language if there's no value in the current language."""
|
||||||
|
|||||||
@@ -9,4 +9,4 @@ lines_between_types=1
|
|||||||
include_trailing_comma=True
|
include_trailing_comma=True
|
||||||
not_skip=__init__.py
|
not_skip=__init__.py
|
||||||
known_standard_library=dataclasses
|
known_standard_library=dataclasses
|
||||||
known_third_party=django_bleach,bleach
|
known_third_party=django_bleach,bleach,pytest
|
||||||
|
|||||||
2
setup.py
2
setup.py
@@ -36,7 +36,7 @@ with open(
|
|||||||
|
|
||||||
setup(
|
setup(
|
||||||
name="django-localized-fields",
|
name="django-localized-fields",
|
||||||
version="6.1",
|
version="6.4",
|
||||||
packages=find_packages(exclude=["tests"]),
|
packages=find_packages(exclude=["tests"]),
|
||||||
include_package_data=True,
|
include_package_data=True,
|
||||||
license="MIT License",
|
license="MIT License",
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
import copy
|
import copy
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
from django import forms
|
from django import forms
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.db import models
|
from django.db import models
|
||||||
@@ -215,6 +217,53 @@ class LocalizedSlugFieldTestCase(TestCase):
|
|||||||
for lang_code, lang_name in settings.LANGUAGES:
|
for lang_code, lang_name in settings.LANGUAGES:
|
||||||
assert obj.slug.get(lang_code) == "title-%s" % lang_name.lower()
|
assert obj.slug.get(lang_code) == "title-%s" % lang_name.lower()
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def test_disable(cls):
|
||||||
|
"""Tests whether disabling auto-slugging works."""
|
||||||
|
|
||||||
|
Model = get_fake_model(
|
||||||
|
{
|
||||||
|
"title": LocalizedField(),
|
||||||
|
"slug": LocalizedUniqueSlugField(
|
||||||
|
populate_from="title", enabled=False
|
||||||
|
),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
obj = Model()
|
||||||
|
obj.title = "test"
|
||||||
|
|
||||||
|
# should raise IntegrityError because auto-slugging
|
||||||
|
# is disabled and the slug field is NULL
|
||||||
|
with pytest.raises(IntegrityError):
|
||||||
|
obj.save()
|
||||||
|
|
||||||
|
@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
|
@classmethod
|
||||||
def test_unique_slug(cls):
|
def test_unique_slug(cls):
|
||||||
"""Tests whether unique slugs are properly generated."""
|
"""Tests whether unique slugs are properly generated."""
|
||||||
@@ -248,10 +297,13 @@ class LocalizedSlugFieldTestCase(TestCase):
|
|||||||
"""Tests whether the :see:deconstruct function properly retains options
|
"""Tests whether the :see:deconstruct function properly retains options
|
||||||
specified in the constructor."""
|
specified in the constructor."""
|
||||||
|
|
||||||
field = LocalizedUniqueSlugField(populate_from="title")
|
field = LocalizedUniqueSlugField(
|
||||||
|
enabled=False, immutable=True, populate_from="title"
|
||||||
|
)
|
||||||
_, _, _, kwargs = field.deconstruct()
|
_, _, _, kwargs = field.deconstruct()
|
||||||
|
|
||||||
assert "populate_from" in kwargs
|
assert not kwargs["enabled"]
|
||||||
|
assert kwargs["immutable"]
|
||||||
assert kwargs["populate_from"] == field.populate_from
|
assert kwargs["populate_from"] == field.populate_from
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
|||||||
@@ -38,6 +38,17 @@ class LocalizedValueTestCase(TestCase):
|
|||||||
for lang_code, _ in settings.LANGUAGES:
|
for lang_code, _ in settings.LANGUAGES:
|
||||||
assert getattr(value, lang_code) is None
|
assert getattr(value, lang_code) is None
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def test_is_empty():
|
||||||
|
"""Tests whether a newly constructed :see:LocalizedValue without any
|
||||||
|
content is considered "empty"."""
|
||||||
|
|
||||||
|
value = LocalizedValue()
|
||||||
|
assert value.is_empty()
|
||||||
|
|
||||||
|
value.set(settings.LANGUAGE_CODE, "my value")
|
||||||
|
assert not value.is_empty()
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def test_init_array():
|
def test_init_array():
|
||||||
"""Tests whether the __init__ function of :see:LocalizedValue properly
|
"""Tests whether the __init__ function of :see:LocalizedValue properly
|
||||||
|
|||||||
Reference in New Issue
Block a user