def _get_any_translated_model(self, meta=None): """ Return any available translation. Returns None if there are no translations at all. """ if meta is None: meta = self._parler_meta.root tr_model = meta.model local_cache = self._translations_cache[tr_model] if local_cache: # There is already a language available in the case. No need for queries. # Give consistent answers if they exist. try: return local_cache.get(self._current_language, None) \ or local_cache.get(self.get_fallback_language(), None) \ or next(t for t in six.itervalues(local_cache) if t is not MISSING) # Skip fallback markers. except StopIteration: pass try: # Use prefetch if available, otherwise perform separate query. prefetch = self._get_prefetched_translations(meta=meta) if prefetch is not None: translation = prefetch[0] # Already a list else: translation = self._get_translated_queryset(meta=meta)[0] except IndexError: return None else: local_cache[translation.language_code] = translation _cache_translation(translation) return translation
def _get_any_translated_model(self): """ Return any available translation. Returns None if there are no translations at all. """ if self._translations_cache: # There is already a language available in the case. No need for queries. # Give consistent answers if they exist. try: return self._translations_cache.get(self._current_language, None) \ or self._translations_cache.get(self.get_fallback_language(), None) \ or next(t for t in six.itervalues(self._translations_cache) if t if not None) # Skip fallback markers. except StopIteration: pass try: # Use prefetch if available, otherwise perform separate query. qs = self._get_translated_queryset() if qs._prefetch_done: translation = list(qs)[0] else: translation = qs[0] except IndexError: return None else: self._translations_cache[translation.language_code] = translation _cache_translation(translation) return translation
def save_base(self, raw=False, using=None, **kwargs): # As of Django 1.8, not calling translations.activate() or disabling the translation # causes get_language() to explicitly return None instead of LANGUAGE_CODE. # This helps developers find solutions by bailing out properly. # # Either use translation.activate() first, or pass the language code explicitly via # MyModel.objects.language('en').create(..) assert self.language_code is not None, ""\ "No language is set or detected for this TranslatableModelMixin.\n" \ "Is the translations system initialized?" # Send the pre_save signal using = using or router.db_for_write(self.__class__, instance=self) record_exists = self.pk is not None # Ignoring force_insert/force_update for now. if not self._meta.auto_created: signals.pre_translation_save.send( sender=self.shared_model, instance=self, raw=raw, using=using ) # Perform save super(TranslatedFieldsModel, self).save_base(raw=raw, using=using, **kwargs) self._original_values = self._get_field_values() _cache_translation(self) # Send the post_save signal if not self._meta.auto_created: signals.post_translation_save.send( sender=self.shared_model, instance=self, created=(not record_exists), raw=raw, using=using )
def save_base(self, raw=False, using=None, **kwargs): # Send the pre_save signal using = using or router.db_for_write(self.__class__, instance=self) record_exists = self.pk is not None # Ignoring force_insert/force_update for now. if not self._meta.auto_created: signals.pre_translation_save.send(sender=self.shared_model, instance=self, raw=raw, using=using) # Perform save super(TranslatedFieldsModel, self).save_base(raw=raw, using=using, **kwargs) self._original_values = self._get_field_values() _cache_translation(self) # Send the post_save signal if not self._meta.auto_created: signals.post_translation_save.send( sender=self.shared_model, instance=self, created=(not record_exists), raw=raw, using=using )
def _get_any_translated_model(self): """ Return any available translation. Returns None if there are no translations at all. """ if self._translations_cache: # There is already a language available in the case. No need for queries. # Give consistent answers if they exist. try: return self._translations_cache.get(self._current_language, None) \ or self._translations_cache.get(self.get_fallback_language(), None) \ or next(t for t in self._translations_cache.itervalues() if t if not None) # Skip fallback markers. except StopIteration: pass try: translation = self._translations_model.objects.using(self._state.db).filter(master=self)[0] except IndexError: return None else: self._translations_cache[translation.language_code] = translation _cache_translation(translation) return translation
def save_base(self, raw=False, using=None, **kwargs): # Send the pre_save signal using = using or router.db_for_write(self.__class__, instance=self) record_exists = self.pk is not None # Ignoring force_insert/force_update for now. if not self._meta.auto_created: signals.pre_translation_save.send(sender=self.shared_model, instance=self, raw=raw, using=using) # Perform save super(TranslatedFieldsModel, self).save_base(raw=raw, using=using, **kwargs) self._original_values = self._get_field_values() _cache_translation(self) # Send the post_save signal if not self._meta.auto_created: signals.post_translation_save.send(sender=self.shared_model, instance=self, created=(not record_exists), raw=raw, using=using)
def _get_any_translated_model(self): """ Return any available translation. Returns None if there are no translations at all. """ if self._translations_cache: # There is already a language available in the case. No need for queries. # Give consistent answers if they exist. try: return self._translations_cache.get(self._current_language, None) \ or self._translations_cache.get(self.get_fallback_language(), None) \ or next(t for t in self._translations_cache.itervalues() if t if not None) # Skip fallback markers. except StopIteration: pass try: translation = self._translations_model.objects.using( self._state.db).filter(master=self)[0] except IndexError: return None else: self._translations_cache[translation.language_code] = translation _cache_translation(translation) return translation
def _get_translated_model(self, language_code=None, use_fallback=False, auto_create=False): """ Fetch the translated fields model. """ if not self._translations_model or not self._translations_field: raise ImproperlyConfigured("No translation is assigned to the current model!") if not language_code: language_code = self._current_language # 1. fetch the object from the local cache try: object = self._translations_cache[language_code] # If cached object indicates the language doesn't exist, need to query the fallback. if object is not None: return object except KeyError: # 2. No cache, need to query # Get via self.TRANSLATIONS_FIELD.get(..) so it also uses the prefetch/select_related cache. # Check that this object already exists, would be pointless otherwise to check for a translation. if not self._state.adding: # 2.1, fetch from memcache object = get_cached_translation(self, language_code) if object is not None: # Track in local cache self._translations_cache[language_code] = object return object else: # 2.2, fetch from database accessor = getattr(self, self._translations_field) try: object = accessor.get(language_code=language_code) except self._translations_model.DoesNotExist: pass else: self._translations_cache[language_code] = object _cache_translation(object) # Store in memcached return object # Not in cache, or default. # Not fetched from DB # 3. Auto create? if auto_create: # Auto create policy first (e.g. a __set__ call) object = self._translations_model( language_code=language_code, master=self # ID might be None at this point ) self._translations_cache[language_code] = object # Not stored in memcached here yet, first fill + save it. return object # 4. Fallback? fallback_msg = None lang_dict = get_language_settings(language_code) if use_fallback and (lang_dict['fallback'] != language_code): # Jump to fallback language, return directly. # Don't cache under this language_code self._translations_cache[language_code] = None # explicit marker that language query was tried before. try: return self._get_translated_model(lang_dict['fallback'], use_fallback=False, auto_create=auto_create) except self._translations_model.DoesNotExist: fallback_msg = u" (tried fallback {0})".format(lang_dict['fallback']) # None of the above, bail out! raise self._translations_model.DoesNotExist( u"{0} does not have a translation for the current language!\n" u"{0} ID #{1}, language={2}{3}".format(self._meta.verbose_name, self.pk, language_code, fallback_msg or '' ))
def _get_translated_model(self, language_code=None, use_fallback=False, auto_create=False): """ Fetch the translated fields model. """ if not self._translations_model or not self._translations_field: raise ImproperlyConfigured("No translation is assigned to the current model!") if not language_code: language_code = self._current_language # 1. fetch the object from the local cache try: object = self._translations_cache[language_code] # If cached object indicates the language doesn't exist, need to query the fallback. if object is not None: return object except KeyError: # 2. No cache, need to query # Check that this object already exists, would be pointless otherwise to check for a translation. if not self._state.adding and self.pk: qs = self._get_translated_queryset() if qs._prefetch_done: # 2.1, use prefetched data # If the object is not found in the prefetched data (which contains all translations), # it's pointless to check for memcached (2.2) or perform a single query (2.3) for object in qs: if object.language_code == language_code: self._translations_cache[language_code] = object _cache_translation(object) # Store in memcached return object else: # 2.2, fetch from memcached object = get_cached_translation(self, language_code, use_fallback=use_fallback) if object is not None: # Track in local cache if object.language_code != language_code: self._translations_cache[language_code] = None # Set fallback marker self._translations_cache[object.language_code] = object return object else: # 2.3, fetch from database try: object = qs.get(language_code=language_code) except self._translations_model.DoesNotExist: pass else: self._translations_cache[language_code] = object _cache_translation(object) # Store in memcached return object # Not in cache, or default. # Not fetched from DB # 3. Auto create? if auto_create: # Auto create policy first (e.g. a __set__ call) object = self._translations_model( language_code=language_code, master=self # ID might be None at this point ) self._translations_cache[language_code] = object # Not stored in memcached here yet, first fill + save it. return object # 4. Fallback? fallback_msg = None lang_dict = get_language_settings(language_code) if use_fallback and (lang_dict['fallback'] != language_code): # Explicitly set a marker for the fact that this translation uses the fallback instead. # Avoid making that query again. self._translations_cache[language_code] = None # None value is the marker. if not self._state.adding or self.pk: _cache_translation_needs_fallback(self, language_code) # Jump to fallback language, return directly. # Don't cache under this language_code try: return self._get_translated_model(lang_dict['fallback'], use_fallback=False, auto_create=auto_create) except self._translations_model.DoesNotExist: fallback_msg = " (tried fallback {0})".format(lang_dict['fallback']) # None of the above, bail out! raise self._translations_model.DoesNotExist( "{0} does not have a translation for the current language!\n" "{0} ID #{1}, language={2}{3}".format(self._meta.verbose_name, self.pk, language_code, fallback_msg or '' ))
def _get_translated_model(self, language_code=None, use_fallback=False, auto_create=False, meta=None): """ Fetch the translated fields model. """ if self._parler_meta is None: raise ImproperlyConfigured("No translation is assigned to the current model!") if self._translations_cache is None: raise RuntimeError("Accessing translated fields before super.__init__() is not possible.") if not language_code: language_code = self._current_language if meta is None: meta = self._parler_meta.root # work on base model by default local_cache = self._translations_cache[meta.model] # 1. fetch the object from the local cache try: object = local_cache[language_code] # If cached object indicates the language doesn't exist, need to query the fallback. if object is not MISSING: return object except KeyError: # 2. No cache, need to query # Check that this object already exists, would be pointless otherwise to check for a translation. if not self._state.adding and self.pk is not None: prefetch = self._get_prefetched_translations(meta=meta) if prefetch is not None: # 2.1, use prefetched data # If the object is not found in the prefetched data (which contains all translations), # it's pointless to check for memcached (2.2) or perform a single query (2.3) for object in prefetch: if object.language_code == language_code: local_cache[language_code] = object _cache_translation(object) # Store in memcached return object else: # 2.2, fetch from memcached object = get_cached_translation(self, language_code, related_name=meta.rel_name, use_fallback=use_fallback) if object is not None: # Track in local cache if object.language_code != language_code: local_cache[language_code] = MISSING # Set fallback marker local_cache[object.language_code] = object return object elif local_cache.get(language_code, None) is MISSING: # If get_cached_translation() explicitly set the "does not exist" marker, # there is no need to try a database query. pass else: # 2.3, fetch from database try: object = self._get_translated_queryset(meta).get(language_code=language_code) except meta.model.DoesNotExist: pass else: local_cache[language_code] = object _cache_translation(object) # Store in memcached return object # Not in cache, or default. # Not fetched from DB # 3. Auto create? if auto_create: # Auto create policy first (e.g. a __set__ call) kwargs = { 'language_code': language_code, } if self.pk: # ID might be None at this point, and Django 1.8 does not allow that. kwargs['master'] = self object = meta.model(**kwargs) local_cache[language_code] = object # Not stored in memcached here yet, first fill + save it. return object # 4. Fallback? fallback_msg = None lang_dict = get_language_settings(language_code) if language_code not in local_cache: # Explicitly set a marker for the fact that this translation uses the fallback instead. # Avoid making that query again. local_cache[language_code] = MISSING # None value is the marker. if not self._state.adding or self.pk is not None: _cache_translation_needs_fallback(self, language_code, related_name=meta.rel_name) fallback_choices = [lang_dict['code']] + list(lang_dict['fallbacks']) if use_fallback and fallback_choices: # Jump to fallback language, return directly. # Don't cache under this language_code for fallback_lang in fallback_choices: if fallback_lang == language_code: # Skip the current language, could also be fallback 1 of 2 choices continue try: return self._get_translated_model(fallback_lang, use_fallback=False, auto_create=auto_create, meta=meta) except meta.model.DoesNotExist: pass fallback_msg = " (tried fallbacks {0})".format(', '.join(lang_dict['fallbacks'])) # None of the above, bail out! raise meta.model.DoesNotExist( "{0} does not have a translation for the current language!\n" "{0} ID #{1}, language={2}{3}".format(self._meta.verbose_name, self.pk, language_code, fallback_msg or '' ))
def _update_cache(self, sender, instance, raw, **kwargs): """Update the translations cache when restoring from a revision.""" if raw: # Raw is set to true (only) when restoring from fixtures or, # django-reversion cache._cache_translation(instance)
def _get_translated_model(self, language_code=None, use_fallback=False, auto_create=False): """ Fetch the translated fields model. """ if not self._translations_model or not self._translations_field: raise ImproperlyConfigured( "No translation is assigned to the current model!") if not language_code: language_code = self._current_language # 1. fetch the object from the local cache try: object = self._translations_cache[language_code] # If cached object indicates the language doesn't exist, need to query the fallback. if object is not None: return object except KeyError: # 2. No cache, need to query # Check that this object already exists, would be pointless otherwise to check for a translation. if not self._state.adding and self.pk: qs = self._get_translated_queryset() if qs._prefetch_done: # 2.1, use prefetched data # If the object is not found in the prefetched data (which contains all translations), # it's pointless to check for memcached (2.2) or perform a single query (2.3) for object in qs: if object.language_code == language_code: self._translations_cache[language_code] = object _cache_translation(object) # Store in memcached return object else: # 2.2, fetch from memcached object = get_cached_translation(self, language_code, use_fallback=use_fallback) if object is not None: # Track in local cache if object.language_code != language_code: self._translations_cache[ language_code] = None # Set fallback marker self._translations_cache[object.language_code] = object return object else: # 2.3, fetch from database try: object = qs.get(language_code=language_code) except self._translations_model.DoesNotExist: pass else: self._translations_cache[language_code] = object _cache_translation(object) # Store in memcached return object # Not in cache, or default. # Not fetched from DB # 3. Auto create? if auto_create: # Auto create policy first (e.g. a __set__ call) object = self._translations_model( language_code=language_code, master=self # ID might be None at this point ) self._translations_cache[language_code] = object # Not stored in memcached here yet, first fill + save it. return object # 4. Fallback? fallback_msg = None lang_dict = get_language_settings(language_code) if use_fallback and (lang_dict['fallback'] != language_code): # Explicitly set a marker for the fact that this translation uses the fallback instead. # Avoid making that query again. self._translations_cache[ language_code] = None # None value is the marker. if not self._state.adding or self.pk: _cache_translation_needs_fallback(self, language_code) # Jump to fallback language, return directly. # Don't cache under this language_code try: return self._get_translated_model(lang_dict['fallback'], use_fallback=False, auto_create=auto_create) except self._translations_model.DoesNotExist: fallback_msg = " (tried fallback {0})".format( lang_dict['fallback']) # None of the above, bail out! raise self._translations_model.DoesNotExist( "{0} does not have a translation for the current language!\n" "{0} ID #{1}, language={2}{3}".format(self._meta.verbose_name, self.pk, language_code, fallback_msg or ''))
def _get_translated_model(self, language_code=None, use_fallback=False, auto_create=False, meta=None): """ Fetch the translated fields model. """ if self._parler_meta is None: raise ImproperlyConfigured( "No translation is assigned to the current model!") if self._translations_cache is None: raise RuntimeError( "Accessing translated fields before super.__init__() is not possible." ) if not language_code: language_code = self._current_language if meta is None: meta = self._parler_meta.root # work on base model by default local_cache = self._translations_cache[meta.model] # 1. fetch the object from the local cache try: object = local_cache[language_code] # If cached object indicates the language doesn't exist, need to query the fallback. if object is not MISSING: return object except KeyError: # 2. No cache, need to query # Check that this object already exists, would be pointless otherwise to check for a translation. if not self._state.adding and self.pk is not None: prefetch = self._get_prefetched_translations(meta=meta) if prefetch is not None: # 2.1, use prefetched data # If the object is not found in the prefetched data (which contains all translations), # it's pointless to check for memcached (2.2) or perform a single query (2.3) for object in prefetch: if object.language_code == language_code: local_cache[language_code] = object _cache_translation(object) # Store in memcached return object else: # 2.2, fetch from memcached object = get_cached_translation(self, language_code, related_name=meta.rel_name, use_fallback=use_fallback) if object is not None: # Track in local cache if object.language_code != language_code: local_cache[ language_code] = MISSING # Set fallback marker local_cache[object.language_code] = object return object elif local_cache.get(language_code, None) is MISSING: # If get_cached_translation() explicitly set the "does not exist" marker, # there is no need to try a database query. pass else: # 2.3, fetch from database try: object = self._get_translated_queryset(meta).get( language_code=language_code) except meta.model.DoesNotExist: pass else: local_cache[language_code] = object _cache_translation(object) # Store in memcached return object # Not in cache, or default. # Not fetched from DB # 3. Auto create? if auto_create: # Auto create policy first (e.g. a __set__ call) kwargs = { 'language_code': language_code, } if self.pk: # ID might be None at this point, and Django 1.8 does not allow that. kwargs['master'] = self object = meta.model(**kwargs) local_cache[language_code] = object # Not stored in memcached here yet, first fill + save it. return object # 4. Fallback? fallback_msg = None lang_dict = get_language_settings(language_code) if language_code not in local_cache: # Explicitly set a marker for the fact that this translation uses the fallback instead. # Avoid making that query again. local_cache[language_code] = MISSING # None value is the marker. if not self._state.adding or self.pk is not None: _cache_translation_needs_fallback(self, language_code, related_name=meta.rel_name) if lang_dict['fallback'] != language_code and use_fallback: # Jump to fallback language, return directly. # Don't cache under this language_code try: return self._get_translated_model(lang_dict['fallback'], use_fallback=False, auto_create=auto_create, meta=meta) except meta.model.DoesNotExist: fallback_msg = " (tried fallback {0})".format( lang_dict['fallback']) # None of the above, bail out! raise meta.model.DoesNotExist( "{0} does not have a translation for the current language!\n" "{0} ID #{1}, language={2}{3}".format(self._meta.verbose_name, self.pk, language_code, fallback_msg or ''))
def _get_translated_model(self, language_code=None, use_fallback=False, auto_create=False): """ Fetch the translated fields model. """ if not self._translations_model or not self._translations_field: raise ImproperlyConfigured( "No translation is assigned to the current model!") if not language_code: language_code = self._current_language # 1. fetch the object from the local cache try: object = self._translations_cache[language_code] # If cached object indicates the language doesn't exist, need to query the fallback. if object is not None: return object except KeyError: # 2. No cache, need to query # Get via self.TRANSLATIONS_FIELD.get(..) so it also uses the prefetch/select_related cache. # Check that this object already exists, would be pointless otherwise to check for a translation. if not self._state.adding: # 2.1, fetch from memcache object = get_cached_translation(self, language_code) if object is not None: # Track in local cache self._translations_cache[language_code] = object return object else: # 2.2, fetch from database accessor = getattr(self, self._translations_field) try: object = accessor.get(language_code=language_code) except self._translations_model.DoesNotExist: pass else: self._translations_cache[language_code] = object _cache_translation(object) # Store in memcached return object # Not in cache, or default. # Not fetched from DB # 3. Auto create? if auto_create: # Auto create policy first (e.g. a __set__ call) object = self._translations_model( language_code=language_code, master=self # ID might be None at this point ) self._translations_cache[language_code] = object # Not stored in memcached here yet, first fill + save it. return object # 4. Fallback? fallback_msg = None lang_dict = get_language_settings(language_code) if use_fallback and (lang_dict['fallback'] != language_code): # Jump to fallback language, return directly. # Don't cache under this language_code self._translations_cache[ language_code] = None # explicit marker that language query was tried before. try: return self._get_translated_model(lang_dict['fallback'], use_fallback=False, auto_create=auto_create) except self._translations_model.DoesNotExist: fallback_msg = u" (tried fallback {0})".format( lang_dict['fallback']) # None of the above, bail out! raise self._translations_model.DoesNotExist( u"{0} does not have a translation for the current language!\n" u"{0} ID #{1}, language={2}{3}".format(self._meta.verbose_name, self.pk, language_code, fallback_msg or ''))