Open jacobburrell opened 3 years ago
Can you explain in steps what's happening?
name_en: English name name_es: Spanish name
You save object, and what overriding what?
The input in Status Name [es] will override the contents of Status Name [en] if Spanish is the default. If English is the default, the [es] field will override the contents of the [en field].
The example of the screenshot upon save will result in both [en] and [es] fields having the value of [en]'s.
Thus after save: Status Name [en]: English override Status Name [es]: English override
Now i understand, but have no idea why it happens.
Was it working before last few updates? What versions of django/django-modeltranslation are you using? Are you doing some stuff in signal handlers which may change those fields?
@last-partizan @jacobburrell Hi, is there any update on the issue? I have the same problem. Thank you!
No, there is nothing new.
Please, provide repository with minimal code to reproduce this issue. Try to fix this yourself and make PR.
@last-partizan I suspect that the cache is affected by this issue.
Assume name
is a field that is translated by django model translation.
queryset = queryset.annotate(
foo=Case(
When(Q(name__in=["hoge", "fuga"], then=True),
default=Value(False),
output_field=BooleanField(),
)
)
I define this and call it at some point. Then, when I try to edit a record in the same model as this one from the Django Admin page, model field translation overrides default langauge for both fields. (Looking directly at the DB, we can confirm that it is stored correctly without being overridden)
So I suspect that when the query is executed, the field value is cached and used as is for display on the django admin page.
Is there a function or option to clear the cache?
Thank you!
I don't remember any caching (but i just maintainer, not author). Better check source code yourself.
The problem is in the cache as it was mentioned by @kathmandu777
But the cache is not a cache like redis or memcache. The problem sits in the django.db.models.fields.Field.get_col
that returns self.cached_col
that is actually decorated by @cached_property
from django.utils.functional
.
The fast workaround that works for me was to create custom register
decorator with cleaning field cached properties.
I only tested that admin part works correctly thus there still may be some side effects.
Solution allows to fix an issue as quick as possible, specially for projects that are using old versions of the model translations library. I suppose that there is better way to fix this issue in new versions.
"""
Register Decorator Patch
"""
__all__ = [
'register'
]
# Standard library imports.
import logging
# Related third party imports.
from django.db.models.base import ModelBase
# Local application/library specific imports.
log = logging.getLogger('modeltranslation_patch')
def register(model_or_iterable, raise_exceptions: bool = False, **options):
"""
Patched decorator to fix issue https://github.com/deschler/django-modeltranslation/issues/593
Decorator has 1 more parameter `raise_exceptions` that may be used to control exception raising
in a case if field retrieve from model meta failed
"""
from modeltranslation.translator import translator, TranslationOptions
def wrapper(opts_class):
if not issubclass(opts_class, TranslationOptions):
raise ValueError('Wrapped class must subclass TranslationOptions.')
# >>>>>>>>>>> PATCH BEGIN <<<<<<<<<<<<<<
if isinstance(model_or_iterable, ModelBase):
models = [model_or_iterable]
else:
models = model_or_iterable
for cls in models:
for f_name in opts_class.fields:
try:
f_obj = cls._meta.get_field(f_name)
except Exception as e:
if raise_exceptions:
raise e
log.exception(f'Failed to get field with name `{f_name}` on model {cls.__name__}:\n{e}')
continue
if 'cached_col' in f_obj.__dict__:
del f_obj.__dict__['cached_col']
# >>>>>>>>>>> PATCH END <<<<<<<<<<<<<<
translator.register(models, opts_class, **options)
return opts_class
return wrapper
I have a model called 'Status' with one field, 'name'.
I registered the model:
I registered with and without admin:
I enabled English and Spanish translation and whichever I set my browser configuration to, that's the language that will override the other.
I have other models in the same app that are similar that don't override the same way.