5 Commits
v2.6 ... v2.9

Author SHA1 Message Date
Swen Kooij
ad2ef34546 Bump version number to 2.9 2017-02-15 19:29:29 +02:00
Swen Kooij
1317023160 Bump version number to 2.8 2017-02-15 19:13:40 +02:00
Swen Kooij
ca6b1c88fa Add option include_time to LocalizedUniqueSlugField 2017-02-15 19:13:19 +02:00
Swen Kooij
64c3c06612 Bumped version number to 2.7 2017-02-09 14:57:25 +02:00
Swen Kooij
b121dfc2d7 Added __eq__ operator to LocalizedValue 2017-02-09 14:57:08 +02:00
7 changed files with 93 additions and 11 deletions

View File

@@ -212,6 +212,15 @@ Besides ``LocalizedField``, there's also:
title = LocalizedField()
slug = LocalizedUniqueSlugField(populate_from='title')
By setting the option ``include_time=True``
.. code-block:: python
slug = LocalizedUniqueSlugField(populate_from='title', include_time=True)
You can instruct the field to include a part of the current time into
the resulting slug. This is useful if you're running into a lot of collisions.
* ``LocalizedAutoSlugField``
Automatically creates a slug for every language from the specified field.

View File

@@ -1,4 +1,5 @@
from typing import Callable
from datetime import datetime
from django import forms
from django.conf import settings
@@ -16,6 +17,7 @@ class LocalizedAutoSlugField(LocalizedField):
"""Initializes a new instance of :see:LocalizedAutoSlugField."""
self.populate_from = kwargs.pop('populate_from', None)
self.include_time = kwargs.pop('include_time', False)
super(LocalizedAutoSlugField, self).__init__(
*args,
@@ -30,6 +32,7 @@ class LocalizedAutoSlugField(LocalizedField):
LocalizedAutoSlugField, self).deconstruct()
kwargs['populate_from'] = self.populate_from
kwargs['include_time'] = self.include_time
return name, path, args, kwargs
def formfield(self, **kwargs):
@@ -76,6 +79,9 @@ class LocalizedAutoSlugField(LocalizedField):
if not value:
continue
if self.include_time:
value += '-%s' % datetime.now().microsecond
def is_unique(slug: str, language: str) -> bool:
"""Gets whether the specified slug is unique."""

View File

@@ -7,6 +7,8 @@ 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
@@ -28,6 +30,8 @@ class LocalizedUniqueSlugField(LocalizedAutoSlugField):
kwargs['uniqueness'] = kwargs.pop('uniqueness', get_language_codes())
self.include_time = kwargs.pop('include_time', False)
super(LocalizedUniqueSlugField, self).__init__(
*args,
**kwargs
@@ -35,6 +39,17 @@ class LocalizedUniqueSlugField(LocalizedAutoSlugField):
self.populate_from = kwargs.pop('populate_from')
def deconstruct(self):
"""Deconstructs the field into something the database
can store."""
name, path, args, kwargs = super(
LocalizedUniqueSlugField, self).deconstruct()
kwargs['populate_from'] = self.populate_from
kwargs['include_time'] = self.include_time
return name, path, args, kwargs
def pre_save(self, instance, add: bool):
"""Ran just before the model is saved, allows us to built
the slug.
@@ -70,6 +85,9 @@ class LocalizedUniqueSlugField(LocalizedAutoSlugField):
continue
slug = slugify(value, allow_unicode=True)
if self.include_time:
slug += '-%d' % datetime.now().microsecond
if instance.retries > 0:
slug += '-%d' % instance.retries

View File

@@ -76,6 +76,21 @@ class LocalizedValue:
return value or ''
def __eq__(self, other):
"""Compares :paramref:self to :paramref:other for
equality.
Returns:
True when :paramref:self is equal to :paramref:other.
And False when they are not.
"""
for lang_code, _ in settings.LANGUAGES:
if self.get(lang_code) != other.get(lang_code):
return False
return True
def __repr__(self): # pragma: no cover
"""Gets a textual representation of this object."""

View File

@@ -7,7 +7,7 @@ with open(os.path.join(os.path.dirname(__file__), 'README.rst')) as readme:
setup(
name='django-localized-fields',
version='2.6',
version='2.9',
packages=find_packages(),
include_package_data=True,
license='MIT License',

View File

@@ -100,6 +100,19 @@ class LocalizedValueTestCase(TestCase):
translation.activate(language)
assert str(localized_value) == value
@staticmethod
def test_eq():
"""Tests whether the __eq__ operator
of :see:LocalizedValue works properly."""
a = LocalizedValue({'en': 'a', 'ar': 'b'})
b = LocalizedValue({'en': 'a', 'ar': 'b'})
assert a == b
b.en = 'b'
assert a != b
@staticmethod
def test_str_fallback():
"""Tests whether the :see:LocalizedValue

View File

@@ -43,7 +43,7 @@ class LocalizedSlugFieldTestCase(TestCase):
cls._test_populate(cls.AutoSlugModel)
@classmethod
def test_populate_magic(cls):
def test_populate_unique(cls):
cls._test_populate(cls.MagicSlugModel)
@classmethod
@@ -51,7 +51,7 @@ class LocalizedSlugFieldTestCase(TestCase):
cls._test_populate_multiple_languages(cls.AutoSlugModel)
@classmethod
def test_populate_multiple_languages_magic(cls):
def test_populate_multiple_languages_unique(cls):
cls._test_populate_multiple_languages(cls.MagicSlugModel)
@classmethod
@@ -59,14 +59,35 @@ class LocalizedSlugFieldTestCase(TestCase):
cls._test_unique_slug(cls.AutoSlugModel)
@classmethod
def test_unique_slug_magic(cls):
def test_unique_slug_unique(cls):
cls._test_unique_slug(cls.MagicSlugModel)
def test_unique_slug_magic_max_retries(self):
"""Tests whether the magic slug implementation doesn't
@staticmethod
def test_unique_slug_with_time():
"""Tests whether the primary key is included in
the slug when the 'use_pk' option is enabled."""
title = 'myuniquetitle'
PkModel = get_fake_model(
'PkModel',
{
'title': LocalizedField(),
'slug': LocalizedUniqueSlugField(populate_from='title', include_time=True)
}
)
obj = PkModel()
obj.title.en = title
obj.save()
assert obj.slug.en.startswith('%s-' % title)
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."""
title = 'mymagictitle'
title = 'myuniquetitle'
obj = self.MagicSlugModel()
obj.title.en = title
@@ -83,7 +104,7 @@ class LocalizedSlugFieldTestCase(TestCase):
cls._test_unique_slug_utf(cls.AutoSlugModel)
@classmethod
def test_unique_slug_utf_magic(cls):
def test_unique_slug_utf_unique(cls):
cls._test_unique_slug_utf(cls.MagicSlugModel)
@classmethod
@@ -91,7 +112,7 @@ class LocalizedSlugFieldTestCase(TestCase):
cls._test_deconstruct(LocalizedAutoSlugField)
@classmethod
def test_deconstruct_magic(cls):
def test_deconstruct_unique(cls):
cls._test_deconstruct(LocalizedUniqueSlugField)
@classmethod
@@ -99,7 +120,7 @@ class LocalizedSlugFieldTestCase(TestCase):
cls._test_formfield(LocalizedAutoSlugField)
@classmethod
def test_formfield_magic(cls):
def test_formfield_unique(cls):
cls._test_formfield(LocalizedUniqueSlugField)
@staticmethod
@@ -130,7 +151,7 @@ class LocalizedSlugFieldTestCase(TestCase):
def _test_unique_slug(model):
"""Tests whether unique slugs are properly generated."""
title = 'mymagictitle'
title = 'myuniquetitle'
obj = model()
obj.title.en = title