Exemplo n.º 1
0
    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
Exemplo n.º 2
0
    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
Exemplo n.º 3
0
    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
            )
Exemplo n.º 4
0
    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
Exemplo n.º 5
0
    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
            )
Exemplo n.º 6
0
    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
Exemplo n.º 7
0
    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
            )
Exemplo n.º 8
0
    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
Exemplo n.º 9
0
    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)
Exemplo n.º 10
0
    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
Exemplo n.º 11
0
    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 ''
        ))
Exemplo n.º 12
0
    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 ''
        ))
Exemplo n.º 13
0
    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 ''
        ))
Exemplo n.º 14
0
 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)
Exemplo n.º 15
0
    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 ''))
Exemplo n.º 16
0
    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 ''))
Exemplo n.º 17
0
 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)
Exemplo n.º 18
0
    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 ''))