diff --git a/modeltranslation/admin.py b/modeltranslation/admin.py index 97e3eadf..a271d5c2 100644 --- a/modeltranslation/admin.py +++ b/modeltranslation/admin.py @@ -63,7 +63,7 @@ def formfield_for_dbfield( def patch_translation_field( self, db_field: Field, field: forms.Field, request: HttpRequest, **kwargs: Any ) -> None: - if db_field.name in self.trans_opts.fields: + if db_field.name in self.trans_opts.all_fields: if field.required: field.required = False field.blank = True @@ -140,8 +140,8 @@ def _exclude_original_fields(self, exclude: _ListOrTuple[str] | None = None) -> exclude = tuple() if exclude: exclude_new = tuple(exclude) - return exclude_new + tuple(self.trans_opts.fields.keys()) - return tuple(self.trans_opts.fields.keys()) + return exclude_new + tuple(self.trans_opts.all_fields.keys()) + return tuple(self.trans_opts.all_fields.keys()) def replace_orig_field(self, option: Iterable[str | Sequence[str]]) -> _ListOrTuple[str]: """ @@ -171,11 +171,11 @@ def replace_orig_field(self, option: Iterable[str | Sequence[str]]) -> _ListOrTu if option: option_new = list(option) for opt in option: - if opt in self.trans_opts.fields: + if opt in self.trans_opts.all_fields: index = option_new.index(opt) option_new[index : index + 1] = get_translation_fields(opt) # type: ignore[arg-type] elif isinstance(opt, (tuple, list)) and ( - [o for o in opt if o in self.trans_opts.fields] + [o for o in opt if o in self.trans_opts.all_fields] ): index = option_new.index(opt) option_new[index : index + 1] = self.replace_orig_field(opt) @@ -198,7 +198,7 @@ def localize(sources: Sequence[str], lang: str) -> tuple[str, ...]: "Append lang suffix (if applicable) to field list" def append_lang(source: str) -> str: - if source in self.trans_opts.fields: + if source in self.trans_opts.all_fields: return build_localized_fieldname(source, lang) return source @@ -206,7 +206,7 @@ def append_lang(source: str) -> str: prepopulated_fields: dict[str, Sequence[str]] = {} for dest, sources in self.prepopulated_fields.items(): - if dest in self.trans_opts.fields: + if dest in self.trans_opts.all_fields: for lang in mt_settings.AVAILABLE_LANGUAGES: key = build_localized_fieldname(dest, lang) prepopulated_fields[key] = localize(sources, lang) @@ -273,7 +273,7 @@ def get_translation_field_excludes( if exclude_languages: excl_languages = exclude_languages exclude = [] - for orig_fieldname, translation_fields in self.trans_opts.fields.items(): + for orig_fieldname, translation_fields in self.trans_opts.all_fields.items(): for tfield in translation_fields: if tfield.language in excl_languages and tfield not in exclude: exclude.append(tfield) @@ -301,7 +301,7 @@ def _patch_list_editable(self) -> None: editable_new = list(self.list_editable) display_new = list(self.list_display) for field in self.list_editable: - if field in self.trans_opts.fields: + if field in self.trans_opts.all_fields: index = editable_new.index(field) display_index = display_new.index(field) translation_fields = get_translation_fields(field) @@ -350,7 +350,7 @@ def _group_fieldsets(self, fieldsets: list) -> list: ) temp_fieldsets = {} - for orig_field, trans_fields in self.trans_opts.fields.items(): + for orig_field, trans_fields in self.trans_opts.all_fields.items(): trans_fieldnames = [f.name for f in sorted(trans_fields, key=lambda x: x.name)] if any(f in trans_fieldnames for f in flattened_fieldsets): # Extract the original field's verbose_name for use as this diff --git a/modeltranslation/management/commands/update_translation_fields.py b/modeltranslation/management/commands/update_translation_fields.py index 2c7b171a..07562792 100644 --- a/modeltranslation/management/commands/update_translation_fields.py +++ b/modeltranslation/management/commands/update_translation_fields.py @@ -79,7 +79,7 @@ def handle(self, *args: Any, **options: Any) -> None: self.stdout.write("Updating data of model '%s'" % model) opts = translator.get_options_for_model(model) - for field_name in opts.fields.keys(): + for field_name in opts.all_fields.keys(): def_lang_fieldname = build_localized_fieldname(field_name, lang) # We'll only update fields which do not have an existing value diff --git a/modeltranslation/manager.py b/modeltranslation/manager.py index a7cfad60..31b5a093 100644 --- a/modeltranslation/manager.py +++ b/modeltranslation/manager.py @@ -81,7 +81,7 @@ def append_fallback(model: type[Model], fields: Sequence[str]) -> tuple[set[str] from modeltranslation.translator import translator opts = translator.get_options_for_model(model) - for key, _ in opts.fields.items(): + for key, _ in opts.all_fields.items(): if key in fields_set: langs = resolution_order(get_language(), getattr(model, key).fallback_languages) fields_set = fields_set.union(build_localized_fieldname(key, lang) for lang in langs) @@ -96,7 +96,7 @@ def append_translated(model: type[Model], fields: Sequence[str]) -> set[str]: from modeltranslation.translator import translator opts = translator.get_options_for_model(model) - for key, translated in opts.fields.items(): + for key, translated in opts.all_fields.items(): if key in fields_set: fields_set = fields_set.union(f.name for f in translated) return fields_set diff --git a/modeltranslation/tests/tests.py b/modeltranslation/tests/tests.py index cf5f4733..80158cf6 100644 --- a/modeltranslation/tests/tests.py +++ b/modeltranslation/tests/tests.py @@ -439,7 +439,7 @@ def _test_constructor(self, keywords): n = models.TestModel(**keywords) m = models.TestModel.objects.create(**keywords) opts = translator.translator.get_options_for_model(models.TestModel) - for base_field, trans_fields in opts.fields.items(): + for base_field, trans_fields in opts.all_fields.items(): self._compare_instances(n, m, base_field) for lang_field in trans_fields: self._compare_instances(n, m, lang_field.name) @@ -2268,7 +2268,7 @@ def assertLocalFields(model, local_fields): def assertFields(model, fields): # The given fields are inherited. opts = translator.translator.get_options_for_model(model) - assert set(opts.fields.keys()) == set(fields) + assert set(opts.all_fields.keys()) == set(fields) # Inherited translation fields are available on the model. model_fields = get_field_names(model) for field in fields: diff --git a/modeltranslation/translator.py b/modeltranslation/translator.py index 0f64f8b2..cdd1b345 100644 --- a/modeltranslation/translator.py +++ b/modeltranslation/translator.py @@ -70,7 +70,7 @@ class FieldsAggregationMetaClass(type): Metaclass to handle custom inheritance of fields between classes. """ - fields: Iterable[str] + fields: Sequence[str] def __new__(cls, name: str, bases: tuple[type, ...], attrs: dict[str, Any]) -> type: attrs["fields"] = set(attrs.get("fields", ())) @@ -89,11 +89,11 @@ class TranslationOptions(metaclass=FieldsAggregationMetaClass): attributes. Options instances hold info about translatable fields for a model and its - superclasses. The ``local_fields`` and ``fields`` attributes are mappings + superclasses. The ``local_fields`` and ``all_fields`` attributes are mappings from fields to sets of their translation fields; ``local_fields`` contains only those fields that are handled in the model's database table (those inherited from abstract superclasses, unless there is a concrete superclass - in between in the inheritance chain), while ``fields`` also includes fields + in between in the inheritance chain), while ``all_fields`` also includes fields inherited from concrete supermodels (giving all translated fields available on a model). @@ -112,7 +112,7 @@ def __init__(self, model: Model) -> None: self.registered = False self.related = False self.local_fields: dict[str, set[TranslationField]] = {f: set() for f in self.fields} - self.fields: dict[str, set[TranslationField]] = {f: set() for f in self.fields} + self.all_fields: dict[str, set[TranslationField]] = {f: set() for f in self.fields} self.related_fields: list[str] = [] def validate(self) -> None: @@ -127,7 +127,7 @@ def validate(self) -> None: else: self._check_languages(self.required_languages.keys(), extra=("default",)) for fieldnames in self.required_languages.values(): - if any(f not in self.fields for f in fieldnames): + if any(f not in self.all_fields for f in fieldnames): raise ImproperlyConfigured( "Fieldname in required_languages which is not in fields option." ) @@ -149,24 +149,24 @@ def update(self, other: TranslationOptions): """ if other.model._meta.abstract: self.local_fields.update(other.local_fields) - self.fields.update(other.fields) + self.all_fields.update(other.all_fields) def add_translation_field(self, field: str, translation_field): """ Add a new translation field to both fields dicts. """ self.local_fields[field].add(translation_field) - self.fields[field].add(translation_field) + self.all_fields[field].add(translation_field) def get_field_names(self) -> list[str]: """ Return name of all fields that can be used in filtering. """ - return list(self.fields.keys()) + self.related_fields + return list(self.all_fields.keys()) + self.related_fields def __str__(self) -> str: local = tuple(self.local_fields.keys()) - inherited = tuple(set(self.fields.keys()) - set(local)) + inherited = tuple(set(self.all_fields.keys()) - set(local)) return "%s: %s + %s" % (self.__class__.__name__, local, inherited) @@ -434,10 +434,10 @@ def populate_translation_fields(sender: type[Model], kwargs: Any): opts = translator.get_options_for_model(sender) for key, val in list(kwargs.items()): - if key in opts.fields: + if key in opts.all_fields: if populate == "all": # Set the value for every language. - for translation_field in opts.fields[key]: + for translation_field in opts.all_fields[key]: kwargs.setdefault(translation_field.name, val) elif populate == "default": default = build_localized_fieldname(key, mt_settings.DEFAULT_LANGUAGE)