def save(self, commit=True): if self.instance.pk is None: fail_message = 'created' new = True else: fail_message = 'changed' new = False super(TranslatableModelForm, self).save(True) trans_model = self.instance._meta.translations_model language_code = self.cleaned_data.get('language_code', get_language()) if not new: trans = get_cached_translation(self.instance) if not trans: try: trans = get_translation(self.instance, language_code) except trans_model.DoesNotExist: trans = trans_model() else: trans = trans_model() trans.language_code = language_code trans.master = self.instance trans = save_instance(self, trans, self._meta.fields, fail_message, commit, construct=True) return combine(trans)
def _get_real_instances(self, base_results): """ The logic for this method was taken from django-polymorphic by Bert Constantin (https://github.com/bconstantin/django_polymorphic) and was slightly altered to fit the needs of django-nani. """ # get the primary keys of the shared model results base_ids = [obj.pk for obj in base_results] fallbacks = list(self._translation_fallbacks) # get all translations for the fallbacks chosen for those shared models, # note that this query is *BIG* and might return a lot of data, but it's # arguably faster than running one query for each result or even worse # one query per result per language until we find something translations_manager = self.model._meta.translations_model.objects baseqs = translations_manager.select_related("master") translations = baseqs.filter(language_code__in=fallbacks, master__pk__in=base_ids) fallback_objects = defaultdict(dict) # turn the results into a dict of dicts with shared model primary key as # keys for the first dict and language codes for the second dict for obj in translations: fallback_objects[obj.master.pk][obj.language_code] = obj # iterate over the share dmodel results for instance in base_results: translation = None # find the translation for fallback in fallbacks: translation = fallback_objects[instance.pk].get(fallback, None) if translation is not None: break # if we found a translation, yield the combined result if translation: yield combine(translation) else: # otherwise yield the shared instance only yield instance
def save(self, commit=True): if self.instance.pk is None: fail_message = 'created' new = True else: fail_message = 'changed' new = False super(TranslatableModelForm, self).save(True) trans_model = self.instance._meta.translations_model language_code = self.cleaned_data.get('language_code', get_language()) if not new: trans = get_cached_translation(self.instance) if not trans or trans.language_code != language_code: try: trans = get_translation(self.instance, language_code) except trans_model.DoesNotExist: trans = trans_model() else: trans = trans_model() trans.language_code = language_code trans.master = self.instance trans = save_instance(self, trans, self._meta.fields, fail_message, commit, construct=True) return combine(trans)
def iterator(self): for obj in super(TranslationMixin, self).iterator(): # non-cascade-deletion hack: if not obj.master: yield obj else: yield combine(obj)
def _post_clean(self): if self.instance.pk: try: trans = trans = get_translation(self.instance, self.instance.language_code) trans.master = self.instance self.instance = combine(trans) except self.instance._meta.translations_model.DoesNotExist: language_code = self.cleaned_data.get('language_code', get_language()) self.instance = self.instance.translate(language_code) return super(TranslatableModelForm, self)._post_clean()
def iterator(self): """ If this queryset is not filtered by a language code yet, it should be filtered first by calling self.language. If someone doesn't want a queryset filtered by language, they should use Model.objects.untranslated() """ if not self._language_code: for obj in self.language().iterator(): yield obj else: for obj in super(TranslationQueryset, self).iterator(): # non-cascade-deletion hack: if not obj.master: yield obj else: yield combine(obj)
def _get_real_instances(self, base_results): """ The logic for this method was taken from django-polymorphic by Bert Constantin (https://github.com/bconstantin/django_polymorphic) and was slightly altered to fit the needs of django-nani. """ # get the primary keys of the shared model results base_ids = [obj.pk for obj in base_results] fallbacks = list(self._translation_fallbacks) # get all translations for the fallbacks chosen for those shared models, # note that this query is *BIG* and might return a lot of data, but it's # arguably faster than running one query for each result or even worse # one query per result per language until we find something translations_manager = self.model._meta.translations_model.objects baseqs = translations_manager.select_related('master') translations = baseqs.filter(language_code__in=fallbacks, master__pk__in=base_ids) fallback_objects = defaultdict(dict) # turn the results into a dict of dicts with shared model primary key as # keys for the first dict and language codes for the second dict for obj in translations: fallback_objects[obj.master.pk][obj.language_code] = obj # iterate over the share dmodel results for instance in base_results: translation = None # find the translation for fallback in fallbacks: translation = fallback_objects[instance.pk].get(fallback, None) if translation is not None: break # if we found a translation, yield the combined result if translation: yield combine(translation) else: # otherwise yield the shared instance only logger.error("no translation for %s, type %s" % (instance, type(instance)))
def __get__(self, instance, instance_type=None): if instance is None: return self value = super(ReverseTranslatedSingleRelatedObjectDescriptor, self).__get__(instance, instance_type) return combine(value)