mirror of
https://github.com/Hopiu/django-modeltranslation.git
synced 2026-05-20 18:31:53 +00:00
Make Context Managers (fallbacks and auto_populate) Thread Safe (#657)
This commit is contained in:
parent
57b1c33af6
commit
4927b6cb63
5 changed files with 65 additions and 11 deletions
|
|
@ -4,6 +4,7 @@ from django.core.exceptions import ImproperlyConfigured
|
|||
from django.db.models import fields
|
||||
|
||||
from modeltranslation import settings as mt_settings
|
||||
from modeltranslation.thread_context import fallbacks_enabled
|
||||
from modeltranslation.utils import (
|
||||
get_language,
|
||||
build_localized_fieldname,
|
||||
|
|
@ -350,7 +351,7 @@ class TranslationFieldDescriptor(object):
|
|||
val = getattr(instance, loc_field_name, None)
|
||||
if self.meaningful_value(val, undefined):
|
||||
return val
|
||||
if mt_settings.ENABLE_FALLBACKS and self.fallback_value is not NONE:
|
||||
if fallbacks_enabled() and self.fallback_value is not NONE:
|
||||
return self.fallback_value
|
||||
else:
|
||||
if default is NONE:
|
||||
|
|
|
|||
|
|
@ -17,8 +17,8 @@ from django.db.models.query import QuerySet, ValuesIterable
|
|||
from django.db.models.utils import create_namedtuple_class
|
||||
from django.utils.tree import Node
|
||||
|
||||
from modeltranslation import settings
|
||||
from modeltranslation.fields import TranslationField
|
||||
from modeltranslation.thread_context import auto_populate_mode
|
||||
from modeltranslation.utils import (
|
||||
auto_populate,
|
||||
build_localized_fieldname,
|
||||
|
|
@ -376,7 +376,7 @@ class MultilingualQuerySet(QuerySet):
|
|||
def _populate_mode(self):
|
||||
# Populate can be set using a global setting or a manager method.
|
||||
if self._populate is None:
|
||||
return settings.AUTO_POPULATE
|
||||
return auto_populate_mode()
|
||||
return self._populate
|
||||
|
||||
# This method was not present in django-linguo
|
||||
|
|
|
|||
48
modeltranslation/thread_context.py
Normal file
48
modeltranslation/thread_context.py
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
import threading
|
||||
from typing import Union
|
||||
from typing_extensions import Literal
|
||||
|
||||
from modeltranslation import settings
|
||||
|
||||
|
||||
AutoPopulate = Union[bool, Literal["all", "default", "required"]]
|
||||
|
||||
|
||||
class ModelTranslationThreadLocal(threading.local):
|
||||
"""Holds thread-local data for modeltranslation."""
|
||||
|
||||
auto_populate: Union[AutoPopulate, None] = None
|
||||
enable_fallbacks: Union[bool, None] = None
|
||||
|
||||
|
||||
_mt_thread_context = ModelTranslationThreadLocal()
|
||||
|
||||
|
||||
def set_auto_populate(value: Union[AutoPopulate, None]) -> None:
|
||||
"""Set the auto_populate for the current thread."""
|
||||
_mt_thread_context.auto_populate = value
|
||||
|
||||
|
||||
def set_enable_fallbacks(value: Union[bool, None]) -> None:
|
||||
"""Set the enable_fallbacks for the current thread."""
|
||||
_mt_thread_context.enable_fallbacks = value
|
||||
|
||||
|
||||
def auto_populate_mode() -> AutoPopulate:
|
||||
"""Return the auto_populate mode for the current thread."""
|
||||
auto_populate = _mt_thread_context.auto_populate
|
||||
|
||||
if auto_populate is not None:
|
||||
return auto_populate
|
||||
|
||||
return settings.AUTO_POPULATE
|
||||
|
||||
|
||||
def fallbacks_enabled() -> bool:
|
||||
"""Return whether fallbacks are enabled for the current thread."""
|
||||
enable_fallbacks = _mt_thread_context.enable_fallbacks
|
||||
|
||||
if enable_fallbacks is not None:
|
||||
return enable_fallbacks
|
||||
|
||||
return settings.ENABLE_FALLBACKS
|
||||
|
|
@ -22,6 +22,7 @@ from modeltranslation.manager import (
|
|||
rewrite_lookup_key,
|
||||
append_translated,
|
||||
)
|
||||
from modeltranslation.thread_context import auto_populate_mode
|
||||
from modeltranslation.utils import build_localized_fieldname, parse_field
|
||||
|
||||
|
||||
|
|
@ -389,7 +390,7 @@ def populate_translation_fields(sender, kwargs):
|
|||
defined (for example to make lookups / filtering without resorting to
|
||||
query fallbacks).
|
||||
"""
|
||||
populate = mt_settings.AUTO_POPULATE
|
||||
populate = auto_populate_mode()
|
||||
if not populate:
|
||||
return
|
||||
if populate is True:
|
||||
|
|
|
|||
|
|
@ -6,6 +6,11 @@ from django.utils.translation import get_language_info
|
|||
from django.utils.functional import lazy
|
||||
|
||||
from modeltranslation import settings
|
||||
from modeltranslation.thread_context import (
|
||||
set_auto_populate,
|
||||
set_enable_fallbacks,
|
||||
fallbacks_enabled,
|
||||
)
|
||||
|
||||
|
||||
def get_language():
|
||||
|
|
@ -112,8 +117,9 @@ def resolution_order(lang, override=None):
|
|||
First is always the parameter language, later are fallback languages.
|
||||
Override parameter has priority over FALLBACK_LANGUAGES.
|
||||
"""
|
||||
if not settings.ENABLE_FALLBACKS:
|
||||
if not fallbacks_enabled():
|
||||
return (lang,)
|
||||
|
||||
if override is None:
|
||||
override = {}
|
||||
fallback_for_lang = override.get(lang, settings.FALLBACK_LANGUAGES.get(lang, ()))
|
||||
|
|
@ -141,12 +147,11 @@ def auto_populate(mode='all'):
|
|||
with auto_populate('required'):
|
||||
call_command('loaddata', 'fixture.json')
|
||||
"""
|
||||
current_population_mode = settings.AUTO_POPULATE
|
||||
settings.AUTO_POPULATE = mode
|
||||
set_auto_populate(mode)
|
||||
try:
|
||||
yield
|
||||
finally:
|
||||
settings.AUTO_POPULATE = current_population_mode
|
||||
set_auto_populate(None)
|
||||
|
||||
|
||||
@contextmanager
|
||||
|
|
@ -163,12 +168,11 @@ def fallbacks(enable=True):
|
|||
processing or check if there is a value for the current language (not
|
||||
knowing the language)
|
||||
"""
|
||||
current_enable_fallbacks = settings.ENABLE_FALLBACKS
|
||||
settings.ENABLE_FALLBACKS = enable
|
||||
set_enable_fallbacks(enable)
|
||||
try:
|
||||
yield
|
||||
finally:
|
||||
settings.ENABLE_FALLBACKS = current_enable_fallbacks
|
||||
set_enable_fallbacks(None)
|
||||
|
||||
|
||||
def parse_field(setting, field_name, default):
|
||||
|
|
|
|||
Loading…
Reference in a new issue