mirror of
https://github.com/SectorLabs/django-localized-fields.git
synced 2025-04-24 19:32:53 +03:00
Support for slugging from multiple fields
This commit is contained in:
parent
3b28a5e707
commit
51fc6959d2
@ -1,12 +1,14 @@
|
||||
from typing import Callable, Tuple
|
||||
from typing import Callable, Tuple, Union
|
||||
from datetime import datetime
|
||||
|
||||
from django import forms
|
||||
from django.conf import settings
|
||||
from django.utils import translation
|
||||
from django.utils.text import slugify
|
||||
|
||||
from .field import LocalizedField
|
||||
from ..value import LocalizedValue
|
||||
from ..util import resolve_object_property
|
||||
|
||||
|
||||
class LocalizedAutoSlugField(LocalizedField):
|
||||
@ -147,7 +149,7 @@ class LocalizedAutoSlugField(LocalizedField):
|
||||
]
|
||||
|
||||
@staticmethod
|
||||
def _get_populate_from_value(instance, field_name: str, language: str):
|
||||
def _get_populate_from_value(instance, field_name: Union[str, Tuple[str]], language: str):
|
||||
"""Gets the value to create a slug from in the specified language.
|
||||
|
||||
Arguments:
|
||||
@ -164,5 +166,17 @@ class LocalizedAutoSlugField(LocalizedField):
|
||||
The text to generate a slug for.
|
||||
"""
|
||||
|
||||
value = getattr(instance, field_name, None)
|
||||
return value.get(language)
|
||||
def get_field_value(name):
|
||||
value = resolve_object_property(instance, name)
|
||||
with translation.override(language):
|
||||
return str(value)
|
||||
|
||||
if isinstance(field_name, tuple) or isinstance(field_name, list):
|
||||
value = '-'.join([
|
||||
value
|
||||
for value in [get_field_value(name) for name in field_name]
|
||||
if value
|
||||
])
|
||||
return value
|
||||
|
||||
return get_field_value(field_name)
|
||||
|
@ -19,3 +19,26 @@ def get_language_codes() -> List[str]:
|
||||
lang_code
|
||||
for lang_code, _ in settings.LANGUAGES
|
||||
]
|
||||
|
||||
|
||||
def resolve_object_property(obj, path: str):
|
||||
"""Resolves the value of a property on an object.
|
||||
|
||||
Is able to resolve nested properties. For example,
|
||||
a path can be specified:
|
||||
|
||||
'other.beer.name'
|
||||
|
||||
Raises:
|
||||
AttributeError:
|
||||
In case the property could not be resolved.
|
||||
|
||||
Returns:
|
||||
The value of the specified property.
|
||||
"""
|
||||
|
||||
value = obj
|
||||
for path_part in path.split('.'):
|
||||
value = getattr(value, path_part)
|
||||
|
||||
return value
|
||||
|
@ -1,6 +1,7 @@
|
||||
import copy
|
||||
|
||||
from django import forms
|
||||
from django.db import models
|
||||
from django.conf import settings
|
||||
from django.test import TestCase
|
||||
from django.db.utils import IntegrityError
|
||||
@ -31,6 +32,7 @@ class LocalizedSlugFieldTestCase(TestCase):
|
||||
'LocalizedAutoSlugFieldTestModel',
|
||||
{
|
||||
'title': LocalizedField(),
|
||||
'name': models.CharField(max_length=255),
|
||||
'slug': LocalizedAutoSlugField(populate_from='title')
|
||||
}
|
||||
)
|
||||
@ -39,6 +41,7 @@ class LocalizedSlugFieldTestCase(TestCase):
|
||||
'LocalizedUniqueSlugFieldTestModel',
|
||||
{
|
||||
'title': LocalizedField(),
|
||||
'name': models.CharField(max_length=255),
|
||||
'slug': LocalizedUniqueSlugField(populate_from='title')
|
||||
}
|
||||
)
|
||||
@ -155,6 +158,22 @@ class LocalizedSlugFieldTestCase(TestCase):
|
||||
def test_formfield_unique(cls):
|
||||
cls._test_formfield(LocalizedUniqueSlugField)
|
||||
|
||||
@classmethod
|
||||
def test_populate_multiple_from_fields_auto(cls):
|
||||
cls._test_populate_multiple_from_fields(LocalizedAutoSlugField)
|
||||
|
||||
@classmethod
|
||||
def test_populate_multiple_from_fields_unique(cls):
|
||||
cls._test_populate_multiple_from_fields(LocalizedUniqueSlugField)
|
||||
|
||||
@classmethod
|
||||
def test_populate_multiple_from_fields_fk_auto(cls):
|
||||
cls._test_populate_multiple_from_fields_fk(LocalizedAutoSlugField)
|
||||
|
||||
@classmethod
|
||||
def test_populate_multiple_from_fields_fk_unique(cls):
|
||||
cls._test_populate_multiple_from_fields_fk(LocalizedUniqueSlugField)
|
||||
|
||||
@staticmethod
|
||||
def _test_populate(model):
|
||||
"""Tests whether the populating feature works correctly."""
|
||||
@ -165,6 +184,67 @@ class LocalizedSlugFieldTestCase(TestCase):
|
||||
|
||||
assert obj.slug.get('en') == slugify(obj.title)
|
||||
|
||||
@staticmethod
|
||||
def _test_populate_multiple_from_fields(field_type):
|
||||
"""Tests whether populating the slug from multiple
|
||||
fields works correctly."""
|
||||
|
||||
model = get_fake_model(
|
||||
'_test_populate_multiple_from_fields_' + str(field_type),
|
||||
{
|
||||
'title': LocalizedField(),
|
||||
'name': models.CharField(max_length=255),
|
||||
'slug': field_type(populate_from=('title', 'name'))
|
||||
}
|
||||
)
|
||||
|
||||
obj = model()
|
||||
for lang_code, lang_name in settings.LANGUAGES:
|
||||
obj.name = 'swen'
|
||||
obj.title.set(lang_code, 'title %s' % lang_name)
|
||||
|
||||
obj.save()
|
||||
|
||||
for lang_code, lang_name in settings.LANGUAGES:
|
||||
assert obj.slug.get(lang_code) == 'title-%s-swen' % lang_name.lower()
|
||||
|
||||
@staticmethod
|
||||
def _test_populate_multiple_from_fields_fk(field_type):
|
||||
"""Tests whether populating the slug from multiple
|
||||
fields works correctly."""
|
||||
|
||||
model_fk = get_fake_model(
|
||||
'_test_populate_multiple_from_fields_fk_other_' + str(field_type),
|
||||
{
|
||||
'name': LocalizedField(),
|
||||
}
|
||||
)
|
||||
|
||||
model = get_fake_model(
|
||||
'_test_populate_multiple_from_fields_fk_' + str(field_type),
|
||||
{
|
||||
'title': LocalizedField(),
|
||||
'other': models.ForeignKey(model_fk),
|
||||
'slug': field_type(populate_from=('title', 'other.name'))
|
||||
}
|
||||
)
|
||||
|
||||
other = model_fk.objects.create(name={settings.LANGUAGE_CODE: 'swen'})
|
||||
# for lang_code, lang_name in settings.LANGUAGES:
|
||||
# other.name.set(lang_code, 'swen')
|
||||
|
||||
# other.save()
|
||||
|
||||
obj = model()
|
||||
for lang_code, lang_name in settings.LANGUAGES:
|
||||
obj.other_id = other.id
|
||||
obj.title.set(lang_code, 'title %s' % lang_name)
|
||||
|
||||
obj.save()
|
||||
|
||||
for lang_code, lang_name in settings.LANGUAGES:
|
||||
assert obj.slug.get(lang_code) == 'title-%s-swen' % lang_name.lower()
|
||||
|
||||
@staticmethod
|
||||
def _test_populate_multiple_languages(model):
|
||||
"""Tests whether the populating feature correctly
|
||||
|
Loading…
x
Reference in New Issue
Block a user