def test_get_language_title(self): """Test get_language_title utility function""" language_code = "en" self.assertEqual(get_language_title(language_code), "English") # Test the case where requested language is not in settings. # We can not override settings, since languages in get_language_title() # are initialised during import. So, we use fictional language code. language_code = "xx" try: self.assertEqual(get_language_title(language_code), language_code) except KeyError: self.fail("get_language_title() raises KeyError for missing language")
def test_get_language_title(self): """Test get_language_title utility function""" language_code = 'en' self.assertEqual(get_language_title(language_code), 'English') # Test the case where requested language is not in settings. # We can not override settings, since languages in get_language_title() # are initialised during import. So, we use fictional language code. language_code = 'xx' try: self.assertEqual(get_language_title(language_code), language_code) except KeyError: self.fail( "get_language_title() raises KeyError for missing language")
def render_change_form(self, request, context, add=False, change=False, form_url='', obj=None): """ Insert the language tabs. """ if self._has_translatable_model(): lang_code = self.get_form_language(request, obj) lang = get_language_title(lang_code) available_languages = self.get_available_languages(obj) language_tabs = self.get_language_tabs(request, obj, available_languages) context['language_tabs'] = language_tabs if language_tabs: context['title'] = '%s (%s)' % (context['title'], lang) if not language_tabs.current_is_translated: add = True # lets prepopulated_fields_js work. # Patch form_url to contain the "language" GET parameter. # Otherwise AdminModel.render_change_form will clean the URL # and remove the "language" when coming from a filtered object # list causing the wrong translation to be changed. params = request.GET.dict() params['language'] = lang_code form_url = add_preserved_filters({ 'preserved_filters': urlencode(params), 'opts': self.model._meta }, form_url) # django-fluent-pages uses the same technique if 'default_change_form_template' not in context: context['default_change_form_template'] = self.get_change_form_base_template() #context['base_template'] = self.get_change_form_base_template() return super(TranslatableAdmin, self).render_change_form(request, context, add, change, form_url, obj)
def render_change_form(self, request, context, add=False, change=False, form_url='', obj=None): """ Insert the language tabs. """ if self._has_translatable_model(): lang_code = self.get_form_language(request, obj) lang = get_language_title(lang_code) available_languages = self.get_available_languages(obj) current_is_translated = lang_code in available_languages language_tabs = self.get_language_tabs(request, obj, available_languages) context['current_is_translated'] = current_is_translated context['allow_deletion'] = len(available_languages) > 1 context['language_tabs'] = language_tabs if language_tabs: context['title'] = '%s (%s)' % (context['title'], lang) if not current_is_translated: add = True # lets prepopulated_fields_js work. # django-fluent-pages uses the same technique if 'default_change_form_template' not in context: context['default_change_form_template'] = self.get_change_form_base_template() #context['base_template'] = self.get_change_form_base_template() return super(TranslatableAdmin, self).render_change_form(request, context, add, change, form_url, obj)
def render_change_form(self, request, context, add=False, change=False, form_url='', obj=None): """ Insert the language tabs. """ if self._has_translatable_model(): lang_code = self.get_form_language(request, obj) lang = get_language_title(lang_code) available_languages = self.get_available_languages(obj) language_tabs = self.get_language_tabs(request, obj, available_languages) context['language_tabs'] = language_tabs if language_tabs: context['title'] = '%s (%s)' % (context['title'], lang) if not language_tabs.current_is_translated: add = True # lets prepopulated_fields_js work. # Patch form_url to contain the "language" GET parameter. # Otherwise AdminModel.render_change_form will clean the URL # and remove the "language" when coming from a filtered object # list causing the wrong translation to be changed. params = request.GET.dict() params['language'] = lang_code form_url = add_preserved_filters({ 'preserved_filters': urlencode(params), 'opts': self.model._meta }, form_url) # django-fluent-pages uses the same technique if 'default_change_form_template' not in context: context['default_change_form_template'] = self.default_change_form_template #context['base_template'] = self.get_change_form_base_template() return super(TranslatableAdmin, self).render_change_form(request, context, add, change, form_url, obj)
def get_language_tabs(self, request, obj, available_languages): """ Determine the language tabs to show. """ tabs = [] get = request.GET.copy() # QueryDict object language = self.get_form_language(request, obj) tab_languages = [] base_url = '{0}://{1}{2}'.format( request.is_secure() and 'https' or 'http', request.get_host(), request.path) for lang_dict in appsettings.PARLER_LANGUAGES.get( settings.SITE_ID, ()): code = lang_dict['code'] title = get_language_title(code) get['language'] = code url = '{0}?{1}'.format(base_url, get.urlencode()) if code == language: status = 'current' elif code in available_languages: status = 'available' else: status = 'empty' tabs.append((url, title, code, status)) tab_languages.append(code) # Additional stale translations in the database? if appsettings.PARLER_SHOW_EXCLUDED_LANGUAGE_TABS: for code in available_languages: if code not in tab_languages: get['language'] = code url = '{0}?{1}'.format(base_url, get.urlencode()) if code == language: status = 'current' else: status = 'available' tabs.append((url, get_language_title(code), code, status)) return tabs
def get_language_tabs(self, request, obj, available_languages): """ Determine the language tabs to show. """ tabs = [] get = request.GET.copy() # QueryDict object language = self.get_form_language(request, obj) tab_languages = [] base_url = '{0}://{1}{2}'.format(request.is_secure() and 'https' or 'http', request.get_host(), request.path) for lang_dict in appsettings.PARLER_LANGUAGES.get(settings.SITE_ID, ()): code = lang_dict['code'] title = get_language_title(code) get['language'] = code url = '{0}?{1}'.format(base_url, get.urlencode()) if code == language: status = 'current' elif code in available_languages: status = 'available' else: status = 'empty' tabs.append((url, title, code, status)) tab_languages.append(code) # Additional stale translations in the database? if appsettings.PARLER_SHOW_EXCLUDED_LANGUAGE_TABS: for code in available_languages: if code not in tab_languages: get['language'] = code url = '{0}?{1}'.format(base_url, get.urlencode()) if code == language: status = 'current' else: status = 'available' tabs.append((url, get_language_title(code), code, status)) return tabs
def deletion_not_allowed(self, request, obj, language_code): """ Deletion-not-allowed view. """ opts = self.model._meta context = { 'object': obj.master, 'language_code': language_code, 'opts': opts, 'app_label': opts.app_label, 'language_name': get_language_title(language_code), 'object_name': force_text(opts.verbose_name) } return render(request, self.deletion_not_allowed_template, context)
def deletion_not_allowed(self, request, obj, language_code): """ Deletion-not-allowed view. """ opts = self.model._meta context = { "object": obj.master, "language_code": language_code, "opts": opts, "app_label": opts.app_label, "language_name": get_language_title(language_code), "object_name": force_str(opts.verbose_name), } return render(request, self.deletion_not_allowed_template, context)
def render_change_form(self, request, context, add=False, change=False, form_url='', obj=None): """ Insert the language tabs. """ if self._has_translatable_model(): lang_code = self.get_form_language(request, obj) lang = get_language_title(lang_code) available_languages = self.get_available_languages(obj) current_is_translated = lang_code in available_languages language_tabs = self.get_language_tabs(request, obj, available_languages) context['current_is_translated'] = current_is_translated context['allow_deletion'] = len(available_languages) > 1 context['language_tabs'] = language_tabs if language_tabs: context['title'] = '%s (%s)' % (context['title'], lang) if not current_is_translated: add = True # lets prepopulated_fields_js work. # django-fluent-pages uses the same technique if 'default_change_form_template' not in context: context[ 'default_change_form_template'] = self.get_change_form_base_template( ) #context['base_template'] = self.get_change_form_base_template() return super(TranslatableAdmin, self).render_change_form(request, context, add, change, form_url, obj)
def delete_translation(self, request, object_id, language_code): """ The 'delete translation' admin view for this model. """ opts = self.model._meta root_model = self.model._parler_meta.root_model # Get object and translation shared_obj = self.get_object(request, unquote(object_id)) if shared_obj is None: raise Http404 shared_obj.set_current_language(language_code) try: translation = root_model.objects.get(master=shared_obj, language_code=language_code) except root_model.DoesNotExist: raise Http404 if not self.has_delete_permission(request, translation): raise PermissionDenied if len(self.get_available_languages(shared_obj)) <= 1: return self.deletion_not_allowed(request, translation, language_code) # Populate deleted_objects, a data structure of all related objects that # will also be deleted. using = router.db_for_write(root_model) # NOTE: all same DB for now. lang = get_language_title(language_code) # There are potentially multiple objects to delete; # the translation object at the base level, # and additional objects that can be added by inherited models. deleted_objects = [] perms_needed = False protected = [] # Extend deleted objects with the inlines. for qs in self.get_translation_objects( request, translation.language_code, obj=shared_obj, inlines=self.delete_inline_translations, ): if isinstance(qs, (list, tuple)): qs_opts = qs[0]._meta else: qs_opts = qs.model._meta if django.VERSION >= (2, 1): deleted_result = get_deleted_objects(qs, request, self.admin_site) else: deleted_result = get_deleted_objects(qs, qs_opts, request.user, self.admin_site, using) (del2, model_counts, perms2, protected2) = deleted_result deleted_objects += del2 perms_needed = perms_needed or perms2 protected += protected2 if request.POST: # The user has already confirmed the deletion. if perms_needed: raise PermissionDenied obj_display = _("{0} translation of {1}").format( lang, force_str(translation)) # in hvad: (translation.master) self.log_deletion(request, translation, obj_display) self.delete_model_translation(request, translation) self.message_user( request, _('The %(name)s "%(obj)s" was deleted successfully.') % dict(name=force_str(opts.verbose_name), obj=force_str(obj_display)), ) if self.has_change_permission(request, None): info = opts.app_label, opts.model_name return HttpResponseRedirect( reverse( "admin:{}_{}_change".format(*info), args=(object_id, ), current_app=self.admin_site.name, )) else: return HttpResponseRedirect( reverse("admin:index", current_app=self.admin_site.name)) object_name = _("{0} Translation").format(force_str(opts.verbose_name)) if perms_needed or protected: title = _("Cannot delete %(name)s") % {"name": object_name} else: title = _("Are you sure?") context = { "title": title, "object_name": object_name, "object": translation, "deleted_objects": deleted_objects, "perms_lacking": perms_needed, "protected": protected, "opts": opts, "app_label": opts.app_label, } # Small hack for django-polymorphic-tree. # This makes sure the breadcrumb renders correctly, # and avoids errors when the child model is not registered in the admin. if hasattr(self, "base_model"): context.update({ "base_opts": self.base_model._meta, }) return render( request, self.delete_confirmation_template or [ f"admin/{opts.app_label}/{opts.object_name.lower()}/delete_confirmation.html", "admin/%s/delete_confirmation.html" % opts.app_label, "admin/delete_confirmation.html", ], context, )
def __str__(self): # use format to avoid weird error in django 1.4 # TypeError: coercing to Unicode: need string or buffer, __proxy__ found return "{0}".format(get_language_title(self.language_code))
def __unicode__(self): return get_language_title(self.language_code)
def __unicode__(self): # use format to avoid weird error in django 1.4 # TypeError: coercing to Unicode: need string or buffer, __proxy__ found return "{0}".format(get_language_title(self.language_code))
def delete_translation(self, request, object_id, language_code): """ The 'delete translation' admin view for this model. """ opts = self.model._meta translations_model = self.model._translations_model try: translation = translations_model.objects.select_related('master').get(master=unquote(object_id), language_code=language_code) except translations_model.DoesNotExist: raise Http404 if not self.has_delete_permission(request, translation): raise PermissionDenied if self.get_available_languages(translation.master).count() <= 1: return self.deletion_not_allowed(request, translation, language_code) # Populate deleted_objects, a data structure of all related objects that # will also be deleted. using = router.db_for_write(translations_model) lang = get_language_title(language_code) (deleted_objects, perms_needed, protected) = get_deleted_objects( [translation], translations_model._meta, request.user, self.admin_site, using) # Extend deleted objects with the inlines. if self.delete_inline_translations: shared_obj = translation.master for inline, qs in self._get_inline_translations(request, translation.language_code, obj=shared_obj): (del2, perms2, protected2) = get_deleted_objects(qs, qs.model._meta, request.user, self.admin_site, using) deleted_objects += del2 perms_needed = perms_needed or perms2 protected += protected2 if request.POST: # The user has already confirmed the deletion. if perms_needed: raise PermissionDenied obj_display = _('{0} translation of {1}').format(lang, force_text(translation)) # in hvad: (translation.master) self.log_deletion(request, translation, obj_display) self.delete_model_translation(request, translation) self.message_user(request, _('The %(name)s "%(obj)s" was deleted successfully.') % dict( name=force_text(opts.verbose_name), obj=force_text(obj_display) )) if self.has_change_permission(request, None): return HttpResponseRedirect(reverse('admin:{0}_{1}_changelist'.format(opts.app_label, opts.module_name))) else: return HttpResponseRedirect(reverse('admin:index')) object_name = _('{0} Translation').format(force_text(opts.verbose_name)) if perms_needed or protected: title = _("Cannot delete %(name)s") % {"name": object_name} else: title = _("Are you sure?") context = { "title": title, "object_name": object_name, "object": translation, "deleted_objects": deleted_objects, "perms_lacking": perms_needed, "protected": protected, "opts": opts, "app_label": opts.app_label, } return render(request, self.delete_confirmation_template or [ "admin/%s/%s/delete_confirmation.html" % (opts.app_label, opts.object_name.lower()), "admin/%s/delete_confirmation.html" % opts.app_label, "admin/delete_confirmation.html" ], context)
def delete_translation(self, request, object_id, language_code): """ The 'delete translation' admin view for this model. """ opts = self.model._meta root_model = self.model._parler_meta.root_model # Get object and translation shared_obj = self.get_object(request, unquote(object_id)) if shared_obj is None: raise Http404 shared_obj.set_current_language(language_code) try: translation = root_model.objects.get(master=shared_obj, language_code=language_code) except root_model.DoesNotExist: raise Http404 if not self.has_delete_permission(request, translation): raise PermissionDenied if self.get_available_languages(shared_obj).count() <= 1: return self.deletion_not_allowed(request, translation, language_code) # Populate deleted_objects, a data structure of all related objects that # will also be deleted. using = router.db_for_write(root_model) # NOTE: all same DB for now. lang = get_language_title(language_code) # There are potentially multiple objects to delete; # the translation object at the base level, # and additional objects that can be added by inherited models. deleted_objects = [] perms_needed = False protected = [] # Extend deleted objects with the inlines. for qs in self.get_translation_objects( request, translation.language_code, obj=shared_obj, inlines=self.delete_inline_translations): if isinstance(qs, (list, tuple)): qs_opts = qs[0]._meta else: qs_opts = qs.model._meta deleted_result = get_deleted_objects(qs, qs_opts, request.user, self.admin_site, using) if django.VERSION >= (1, 8): (del2, model_counts, perms2, protected2) = deleted_result else: (del2, perms2, protected2) = deleted_result deleted_objects += del2 perms_needed = perms_needed or perms2 protected += protected2 if request.POST: # The user has already confirmed the deletion. if perms_needed: raise PermissionDenied obj_display = _('{0} translation of {1}').format( lang, force_text(translation)) # in hvad: (translation.master) self.log_deletion(request, translation, obj_display) self.delete_model_translation(request, translation) self.message_user( request, _('The %(name)s "%(obj)s" was deleted successfully.') % dict(name=force_text(opts.verbose_name), obj=force_text(obj_display))) if self.has_change_permission(request, None): return HttpResponseRedirect( reverse('admin:{0}_{1}_changelist'.format( opts.app_label, opts.model_name if django.VERSION >= (1, 7) else opts.module_name))) else: return HttpResponseRedirect(reverse('admin:index')) object_name = _('{0} Translation').format(force_text( opts.verbose_name)) if perms_needed or protected: title = _("Cannot delete %(name)s") % {"name": object_name} else: title = _("Are you sure?") context = { "title": title, "object_name": object_name, "object": translation, "deleted_objects": deleted_objects, "perms_lacking": perms_needed, "protected": protected, "opts": opts, "app_label": opts.app_label, } return render( request, self.delete_confirmation_template or [ "admin/%s/%s/delete_confirmation.html" % (opts.app_label, opts.object_name.lower()), "admin/%s/delete_confirmation.html" % opts.app_label, "admin/delete_confirmation.html" ], context)
def delete_translation(self, request, object_id, language_code): """ The 'delete translation' admin view for this model. """ opts = self.model._meta root_model = self.model._parler_meta.root_model # Get object and translation shared_obj = self.get_object(request, unquote(object_id)) if shared_obj is None: raise Http404 shared_obj.set_current_language(language_code) try: translation = root_model.objects.get(master=shared_obj, language_code=language_code) except root_model.DoesNotExist: raise Http404 if not self.has_delete_permission(request, translation): raise PermissionDenied if len(self.get_available_languages(shared_obj)) <= 1: return self.deletion_not_allowed(request, translation, language_code) # Populate deleted_objects, a data structure of all related objects that # will also be deleted. using = router.db_for_write(root_model) # NOTE: all same DB for now. lang = get_language_title(language_code) # There are potentially multiple objects to delete; # the translation object at the base level, # and additional objects that can be added by inherited models. deleted_objects = [] perms_needed = False protected = [] # Extend deleted objects with the inlines. for qs in self.get_translation_objects(request, translation.language_code, obj=shared_obj, inlines=self.delete_inline_translations): if isinstance(qs, (list, tuple)): qs_opts = qs[0]._meta else: qs_opts = qs.model._meta deleted_result = get_deleted_objects(qs, qs_opts, request.user, self.admin_site, using) if django.VERSION >= (1, 8): (del2, model_counts, perms2, protected2) = deleted_result else: (del2, perms2, protected2) = deleted_result deleted_objects += del2 perms_needed = perms_needed or perms2 protected += protected2 if request.POST: # The user has already confirmed the deletion. if perms_needed: raise PermissionDenied obj_display = _('{0} translation of {1}').format(lang, force_text(translation)) # in hvad: (translation.master) self.log_deletion(request, translation, obj_display) self.delete_model_translation(request, translation) self.message_user(request, _('The %(name)s "%(obj)s" was deleted successfully.') % dict( name=force_text(opts.verbose_name), obj=force_text(obj_display) )) if self.has_change_permission(request, None): info = _get_model_meta(opts) return HttpResponseRedirect(reverse('admin:{0}_{1}_change'.format(*info), args=(object_id,), current_app=self.admin_site.name)) else: return HttpResponseRedirect(reverse('admin:index', current_app=self.admin_site.name)) object_name = _('{0} Translation').format(force_text(opts.verbose_name)) if perms_needed or protected: title = _("Cannot delete %(name)s") % {"name": object_name} else: title = _("Are you sure?") context = { "title": title, "object_name": object_name, "object": translation, "deleted_objects": deleted_objects, "perms_lacking": perms_needed, "protected": protected, "opts": opts, "app_label": opts.app_label, } return render(request, self.delete_confirmation_template or [ "admin/%s/%s/delete_confirmation.html" % (opts.app_label, opts.object_name.lower()), "admin/%s/delete_confirmation.html" % opts.app_label, "admin/delete_confirmation.html" ], context)
def delete_translation(self, request, object_id, language_code): """ The 'delete translation' admin view for this model. """ opts = self.model._meta translations_model = self.model._translations_model try: translation = translations_model.objects.select_related( 'master').get(master=unquote(object_id), language_code=language_code) except translations_model.DoesNotExist: raise Http404 if not self.has_delete_permission(request, translation): raise PermissionDenied if self.get_available_languages(translation.master).count() <= 1: return self.deletion_not_allowed(request, translation, language_code) # Populate deleted_objects, a data structure of all related objects that # will also be deleted. using = router.db_for_write(translations_model) lang = get_language_title(language_code) (deleted_objects, perms_needed, protected) = get_deleted_objects([translation], translations_model._meta, request.user, self.admin_site, using) # Extend deleted objects with the inlines. if self.delete_inline_translations: shared_obj = translation.master for inline, qs in self._get_inline_translations( request, translation.language_code, obj=shared_obj): (del2, perms2, protected2) = get_deleted_objects(qs, qs.model._meta, request.user, self.admin_site, using) deleted_objects += del2 perms_needed = perms_needed or perms2 protected += protected2 if request.POST: # The user has already confirmed the deletion. if perms_needed: raise PermissionDenied obj_display = _('{0} translation of {1}').format( lang, force_text(translation)) # in hvad: (translation.master) self.log_deletion(request, translation, obj_display) self.delete_model_translation(request, translation) self.message_user( request, _('The %(name)s "%(obj)s" was deleted successfully.') % dict(name=force_text(opts.verbose_name), obj=force_text(obj_display))) if self.has_change_permission(request, None): return HttpResponseRedirect( reverse('admin:{0}_{1}_changelist'.format( opts.app_label, opts.module_name))) else: return HttpResponseRedirect(reverse('admin:index')) object_name = _('{0} Translation').format(force_text( opts.verbose_name)) if perms_needed or protected: title = _("Cannot delete %(name)s") % {"name": object_name} else: title = _("Are you sure?") context = { "title": title, "object_name": object_name, "object": translation, "deleted_objects": deleted_objects, "perms_lacking": perms_needed, "protected": protected, "opts": opts, "app_label": opts.app_label, } return render( request, self.delete_confirmation_template or [ "admin/%s/%s/delete_confirmation.html" % (opts.app_label, opts.object_name.lower()), "admin/%s/delete_confirmation.html" % opts.app_label, "admin/delete_confirmation.html" ], context)
def __str__(self): return force_text(get_language_title(self.language_code))