fix(types): Fix fields type (#739)

Most likely, this won't cause any troubles for standard use-cases. But, if you used `get_options_for_model()` and `.fields` from this instance, you need to rename it to `.all_fields`.

BREAKING CHANGE: Rename `fields` (dict with set of TranslationField) to `all_fields`, on the TranslationOptions instance.
This commit is contained in:
Serhii Tereshchenko 2024-05-26 07:29:52 +03:00 committed by GitHub
parent 47f8083576
commit b97c22c197
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 26 additions and 26 deletions

View file

@ -63,7 +63,7 @@ class TranslationBaseModelAdmin(BaseModelAdmin):
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 @@ class TranslationBaseModelAdmin(BaseModelAdmin):
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 @@ class TranslationBaseModelAdmin(BaseModelAdmin):
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 @@ class TranslationBaseModelAdmin(BaseModelAdmin):
"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 @@ class TranslationBaseModelAdmin(BaseModelAdmin):
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 @@ class TranslationBaseModelAdmin(BaseModelAdmin):
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 @@ class TranslationAdmin(TranslationBaseModelAdmin, admin.ModelAdmin):
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 @@ class TranslationAdmin(TranslationBaseModelAdmin, admin.ModelAdmin):
)
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

View file

@ -79,7 +79,7 @@ class Command(BaseCommand):
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

View file

@ -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

View file

@ -439,7 +439,7 @@ class ModeltranslationTest(ModeltranslationTestBase):
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 @@ class ModelInheritanceTest(ModeltranslationTestBase):
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:

View file

@ -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 @@ class TranslationOptions(metaclass=FieldsAggregationMetaClass):
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 @@ class TranslationOptions(metaclass=FieldsAggregationMetaClass):
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 @@ class TranslationOptions(metaclass=FieldsAggregationMetaClass):
"""
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)