diff --git a/localized_fields/descriptor.py b/localized_fields/descriptor.py index 5518b70..65f8512 100644 --- a/localized_fields/descriptor.py +++ b/localized_fields/descriptor.py @@ -59,7 +59,7 @@ class LocalizedValueDescriptor: def __set__(self, instance, value): if isinstance(value, six.string_types): - self.__get__(instance).set(translation.get_language() or - settings.LANGUAGE_CODE, value) + language = translation.get_language() or settings.LANGUAGE_CODE + self.__get__(instance).set(language, value) # pylint: disable=no-member else: instance.__dict__[self.field.name] = value diff --git a/localized_fields/fields/autoslug_field.py b/localized_fields/fields/autoslug_field.py index d7ef10c..537aa46 100644 --- a/localized_fields/fields/autoslug_field.py +++ b/localized_fields/fields/autoslug_field.py @@ -1,4 +1,4 @@ -from typing import Callable +from typing import Callable, Tuple from datetime import datetime from django import forms @@ -69,13 +69,7 @@ class LocalizedAutoSlugField(LocalizedField): slugs = LocalizedValue() - for lang_code, _ in settings.LANGUAGES: - value = self._get_populate_from_value( - instance, - self.populate_from, - lang_code - ) - + for lang_code, value in self._get_populate_values(instance): if not value: continue @@ -128,6 +122,30 @@ class LocalizedAutoSlugField(LocalizedField): return unique_slug + def _get_populate_values(self, instance) -> Tuple[str, str]: + """Gets all values (for each language) from the + specified's instance's `populate_from` field. + + Arguments: + instance: + The instance to get the values from. + + Returns: + A list of (lang_code, value) tuples. + """ + + return [ + ( + lang_code, + self._get_populate_from_value( + instance, + self.populate_from, + lang_code + ), + ) + for lang_code, _ in settings.LANGUAGES + ] + @staticmethod def _get_populate_from_value(instance, field_name: str, language: str): """Gets the value to create a slug from in the specified language. diff --git a/localized_fields/fields/uniqueslug_field.py b/localized_fields/fields/uniqueslug_field.py index 2b2cbe1..ab4cd30 100644 --- a/localized_fields/fields/uniqueslug_field.py +++ b/localized_fields/fields/uniqueslug_field.py @@ -1,6 +1,5 @@ from datetime import datetime -from django.conf import settings from django.utils.text import slugify from django.core.exceptions import ImproperlyConfigured @@ -73,13 +72,7 @@ class LocalizedUniqueSlugField(LocalizedAutoSlugField): slugs = LocalizedValue() - for lang_code, _ in settings.LANGUAGES: - value = self._get_populate_from_value( - instance, - self.populate_from, - lang_code - ) - + for lang_code, value in self._get_populate_values(instance): if not value: continue diff --git a/localized_fields/forms.py b/localized_fields/forms.py index 86d35b3..386f71a 100644 --- a/localized_fields/forms.py +++ b/localized_fields/forms.py @@ -7,7 +7,6 @@ from .value import LocalizedValue from .widgets import LocalizedFieldWidget - class LocalizedFieldForm(forms.MultiValueField): """Form for a localized field, allows editing the field in multiple languages.""" @@ -38,7 +37,7 @@ class LocalizedFieldForm(forms.MultiValueField): for f, w in zip(self.fields, self.widget.widgets): w.is_required = f.required - def compress(self, value: List[str]) -> value_class: + def compress(self, value: List[str]) -> LocalizedValue: """Compresses the values from individual fields into a single :see:LocalizedValue instance. diff --git a/localized_fields/hstore_index.py b/localized_fields/hstore_index.py deleted file mode 100644 index 352d03f..0000000 --- a/localized_fields/hstore_index.py +++ /dev/null @@ -1,132 +0,0 @@ -"""This module is unused, but should be contributed to Django.""" - -from typing import List - -from django.db import models - - -class HStoreIndex(models.Index): - """Allows creating a index on a specific HStore index. - - Note: pieces of code in this class have been copied - from the base class. There was no way around this.""" - - def __init__(self, field: str, keys: List[str], unique: bool=False, - name: str=''): - """Initializes a new instance of :see:HStoreIndex. - - Arguments: - field: - Name of the hstore field for - which's keys to create a index for. - - keys: - The name of the hstore keys to - create the index on. - - unique: - Whether this index should - be marked as UNIQUE. - - name: - The name of the index. If left - empty, one will be generated. - """ - - self.field = field - self.keys = keys - self.unique = unique - - # this will eventually set self.name - super(HStoreIndex, self).__init__( - fields=[field], - name=name - ) - - def get_sql_create_template_values(self, model, schema_editor, using): - """Gets the values for the SQL template. - - Arguments: - model: - The model this index applies to. - - schema_editor: - The schema editor to modify the schema. - - using: - Optional: "USING" statement. - - Returns: - Dictionary of keys to pass into the SQL template. - """ - - fields = [model._meta.get_field(field_name) for field_name, order in self.fields_orders] - tablespace_sql = schema_editor._get_index_tablespace_sql(model, fields) - quote_name = schema_editor.quote_name - - columns = [ - '(%s->\'%s\')' % (self.field, key) - for key in self.keys - ] - - return { - 'table': quote_name(model._meta.db_table), - 'name': quote_name(self.name), - 'columns': ', '.join(columns), - 'using': using, - 'extra': tablespace_sql, - } - - def create_sql(self, model, schema_editor, using=''): - """Gets the SQL to execute when creating the index. - - Arguments: - model: - The model this index applies to. - - schema_editor: - The schema editor to modify the schema. - - using: - Optional: "USING" statement. - - Returns: - SQL string to execute to create this index. - """ - - sql_create_index = schema_editor.sql_create_index - if self.unique: - sql_create_index = sql_create_index.replace('CREATE', 'CREATE UNIQUE') - sql_parameters = self.get_sql_create_template_values(model, schema_editor, using) - return sql_create_index % sql_parameters - - def remove_sql(self, model, schema_editor): - """Gets the SQL to execute to remove this index. - - Arguments: - model: - The model this index applies to. - - schema_editor: - The schema editor to modify the schema. - - Returns: - SQL string to execute to remove this index. - """ - quote_name = schema_editor.quote_name - return schema_editor.sql_delete_index % { - 'table': quote_name(model._meta.db_table), - 'name': quote_name(self.name), - } - - def deconstruct(self): - """Gets the values to pass to :see:__init__ when - re-creating this object.""" - - path = '%s.%s' % (self.__class__.__module__, self.__class__.__name__) - return (path, (), { - 'field': self.field, - 'keys': self.keys, - 'unique': self.unique, - 'name': self.name - }) diff --git a/localized_fields/value.py b/localized_fields/value.py index 50714bc..68fbbe0 100644 --- a/localized_fields/value.py +++ b/localized_fields/value.py @@ -17,7 +17,8 @@ class LocalizedValue(dict): different language. """ - self._interpret_value(keys); + super().__init__({}) + self._interpret_value(keys) def get(self, language: str=None) -> str: """Gets the underlying value in the specified or diff --git a/localized_fields/widgets.py b/localized_fields/widgets.py index ade2b6f..0d6883d 100644 --- a/localized_fields/widgets.py +++ b/localized_fields/widgets.py @@ -15,12 +15,12 @@ class LocalizedFieldWidget(forms.MultiWidget): def __init__(self, *args, **kwargs): """Initializes a new instance of :see:LocalizedFieldWidget.""" - widgets = [] + initial_widgets = [ + self.widget + for _ in settings.LANGUAGES + ] - for _ in settings.LANGUAGES: - widgets.append(self.widget) - - super(LocalizedFieldWidget, self).__init__(widgets, *args, **kwargs) + super().__init__(initial_widgets, *args, **kwargs) def decompress(self, value: LocalizedValue) -> List[str]: """Decompresses the specified value so @@ -36,7 +36,6 @@ class LocalizedFieldWidget(forms.MultiWidget): """ result = [] - for lang_code, _ in settings.LANGUAGES: if value: result.append(value.get(lang_code)) @@ -78,7 +77,8 @@ class AdminLocalizedFieldWidget(LocalizedFieldWidget): } return render_to_string(self.template, context) - def build_widget_attrs(self, widget, value, attrs): + @staticmethod + def build_widget_attrs(widget, value, attrs): attrs = dict(attrs) # Copy attrs to avoid modifying the argument. if (not widget.use_required_attribute(value) or not widget.is_required) \ and 'required' in attrs: diff --git a/tests/fake_model.py b/tests/fake_model.py index 5456219..dc8cf8e 100644 --- a/tests/fake_model.py +++ b/tests/fake_model.py @@ -3,7 +3,6 @@ from django.db.migrations.executor import MigrationExecutor from django.contrib.postgres.operations import HStoreExtension from localized_fields.models import LocalizedModel -from localized_fields.mixins import AtomicSlugRetryMixin def define_fake_model(name='TestModel', fields=None): diff --git a/tests/test_field.py b/tests/test_field.py index 7538c07..b998a46 100644 --- a/tests/test_field.py +++ b/tests/test_field.py @@ -3,7 +3,6 @@ import json from django.conf import settings from django.db.utils import IntegrityError from django.test import TestCase -from django.utils import translation from localized_fields.fields import LocalizedField from localized_fields.forms import LocalizedFieldForm diff --git a/tests/test_model.py b/tests/test_model.py index f9c31ce..974b975 100644 --- a/tests/test_model.py +++ b/tests/test_model.py @@ -34,7 +34,6 @@ class LocalizedModelTestCase(TestCase): assert isinstance(obj.title, LocalizedValue) - @classmethod def test_model_init_kwargs(cls): """Tests whether all :see:LocalizedField diff --git a/tests/test_value.py b/tests/test_value.py index 7d4bd3e..aaffd99 100644 --- a/tests/test_value.py +++ b/tests/test_value.py @@ -1,5 +1,3 @@ -import json - from django.conf import settings from django.test import TestCase from django.utils import translation @@ -164,4 +162,3 @@ class LocalizedValueTestCase(TestCase): value = LocalizedValue('beer') assert value.get(settings.LANGUAGE_CODE) == 'beer' -