Add LocalizedRef expression for extracting the value in the current language

This commit is contained in:
Swen Kooij 2017-05-30 13:38:27 +03:00
parent e5214b07ae
commit 06f7ee15f0
3 changed files with 96 additions and 0 deletions

View File

@ -0,0 +1,25 @@
from django.conf import settings
from django.utils import translation
from psqlextra import expressions
class LocalizedRef(expressions.HStoreRef):
"""Expression that selects the value in a field only in
the currently active language."""
def __init__(self, name: str, lang: str=None):
"""Initializes a new instance of :see:LocalizedRef.
Arguments:
name:
The field/column to select from.
lang:
The language to get the field/column in.
If not specified, the currently active language
is used.
"""
language = lang or translation.get_language() or settings.LANGUAGE_CODE
super().__init__(name, language)

View File

@ -82,6 +82,12 @@ class LocalizedField(HStoreField):
return result return result
# this is for when you select an individual key, it will be string,
# not a dictionary, we'll give it to you as a flat value, not as a
# localized value instance
if not isinstance(value, dict):
return value
return cls.attr_class(value) return cls.attr_class(value)
def to_python(self, value: Union[dict, str, None]) -> LocalizedValue: def to_python(self, value: Union[dict, str, None]) -> LocalizedValue:

65
tests/test_expressions.py Normal file
View File

@ -0,0 +1,65 @@
from django.test import TestCase
from django.db import models
from django.utils import translation
from django.conf import settings
from localized_fields.fields import LocalizedField
from localized_fields.value import LocalizedValue
from localized_fields.expressions import LocalizedRef
from .fake_model import get_fake_model
class LocalizedExpressionsTestCase(TestCase):
"""Tests whether expressions properly work with :see:LocalizedField."""
TestModel1 = None
TestModel2 = None
@classmethod
def setUpClass(cls):
"""Creates the test model in the database."""
super(LocalizedExpressionsTestCase, cls).setUpClass()
cls.TestModel1 = get_fake_model(
'LocalizedExpressionsTestCase2',
{
'name': models.CharField(null=False, blank=False, max_length=255),
}
)
cls.TestModel2 = get_fake_model(
'LocalizedExpressionsTestCase1',
{
'text': LocalizedField(),
'other': models.ForeignKey(cls.TestModel1, related_name='features')
}
)
@classmethod
def test_localized_ref(cls):
"""Tests whether the :see:LocalizedRef expression properly works."""
obj = cls.TestModel1.objects.create(name='bla bla')
for i in range(0, 10):
cls.TestModel2.objects.create(
text=LocalizedValue(dict(en='text_%d_en' % i, ro='text_%d_ro' % i, nl='text_%d_nl' % i)),
other=obj
)
for lang_code, _ in settings.LANGUAGES:
translation.activate(lang_code)
queryset = (
cls.TestModel1.objects
.annotate(
mytexts=LocalizedRef('features__text')
)
.values_list(
'mytexts', flat=True
)
)
for index, value in enumerate(queryset):
assert str(index) in value