From 986e162c5d0a0eb45e21bd3e3d6350a4c7d7af52 Mon Sep 17 00:00:00 2001 From: Karen Tracey Date: Tue, 16 Dec 2008 17:42:18 +0000 Subject: [PATCH] Follow-up to r9656 -- beef up the added test to exercise all (one can hope) paths through the troublesome get_deleted_objects function and fix the resulting errors. Refs #9859. git-svn-id: http://code.djangoproject.com/svn/django/trunk@9657 bcc190cf-cafb-0310-a4f2-bffc1f526a37 --- django/contrib/admin/util.py | 23 ++++++---- .../fixtures/admin-views-unicode.xml | 28 +++++++++++ tests/regressiontests/admin_views/models.py | 46 +++++++++++++++++-- 3 files changed, 86 insertions(+), 11 deletions(-) diff --git a/django/contrib/admin/util.py b/django/contrib/admin/util.py index 2ec507f9245..0900b4e3d9c 100644 --- a/django/contrib/admin/util.py +++ b/django/contrib/admin/util.py @@ -88,14 +88,16 @@ def get_deleted_objects(deleted_objects, perms_needed, user, obj, opts, current_ if not has_admin: # Don't display link to edit, because it either has no # admin or is edited inline. - nh(deleted_objects, current_depth, [u'%s: %s' % (force_unicode(capfirst(related.opts.verbose_name)), sub_obj), []]) + nh(deleted_objects, current_depth, + [u'%s: %s' % (capfirst(related.opts.verbose_name), force_unicode(sub_obj)), []]) else: # Display a link to the admin page. nh(deleted_objects, current_depth, [mark_safe(u'%s: %s' % - (escape(force_unicode(capfirst(related.opts.verbose_name))), - related.opts.app_label, - related.opts.object_name.lower(), - sub_obj._get_pk_val(), sub_obj)), []]) + (escape(capfirst(related.opts.verbose_name)), + related.opts.app_label, + related.opts.object_name.lower(), + sub_obj._get_pk_val(), + escape(sub_obj))), []]) get_deleted_objects(deleted_objects, perms_needed, user, sub_obj, related.opts, current_depth+2, admin_site) else: has_related_objs = False @@ -104,11 +106,16 @@ def get_deleted_objects(deleted_objects, perms_needed, user, obj, opts, current_ if not has_admin: # Don't display link to edit, because it either has no # admin or is edited inline. - nh(deleted_objects, current_depth, [u'%s: %s' % (capfirst(related.opts.verbose_name), force_unicode(sub_obj)), []]) + nh(deleted_objects, current_depth, + [u'%s: %s' % (capfirst(related.opts.verbose_name), force_unicode(sub_obj)), []]) else: # Display a link to the admin page. - nh(deleted_objects, current_depth, [mark_safe(u'%s: %s' % \ - (escape(force_unicode(capfirst(related.opts.verbose_name))), related.opts.app_label, related.opts.object_name.lower(), sub_obj._get_pk_val(), escape(sub_obj))), []]) + nh(deleted_objects, current_depth, [mark_safe(u'%s: %s' % + (escape(capfirst(related.opts.verbose_name)), + related.opts.app_label, + related.opts.object_name.lower(), + sub_obj._get_pk_val(), + escape(sub_obj))), []]) get_deleted_objects(deleted_objects, perms_needed, user, sub_obj, related.opts, current_depth+2, admin_site) # If there were related objects, and the user doesn't have # permission to delete them, add the missing perm to perms_needed. diff --git a/tests/regressiontests/admin_views/fixtures/admin-views-unicode.xml b/tests/regressiontests/admin_views/fixtures/admin-views-unicode.xml index 91bca2e8b58..5652aa18810 100644 --- a/tests/regressiontests/admin_views/fixtures/admin-views-unicode.xml +++ b/tests/regressiontests/admin_views/fixtures/admin-views-unicode.xml @@ -17,6 +17,10 @@ Lærdommer + + <Promo for Lærdommer> + 1 + Norske bostaver æøå skaper problemer <p>Svært frustrerende med UnicodeDecodeErro</p> @@ -32,4 +36,28 @@ <p>Noe innhold</p> 1 + + <Xtra(1) Norske bostaver æøå skaper problemer> + 1 + + + <Xtra(1) Kjærlighet> + 2 + + + <Xtra(1) Kjærlighet> + 3 + + + <Xtra(2) Norske bostaver æøå skaper problemer> + 1 + + + <Xtra(2) Kjærlighet> + 2 + + + <Xtra(2) Kjærlighet> + 3 + diff --git a/tests/regressiontests/admin_views/models.py b/tests/regressiontests/admin_views/models.py index 08cc404603c..050823f6ded 100644 --- a/tests/regressiontests/admin_views/models.py +++ b/tests/regressiontests/admin_views/models.py @@ -1,3 +1,4 @@ +# -*- coding: utf-8 -*- from django.db import models from django.contrib import admin @@ -28,16 +29,43 @@ class Book(models.Model): """ A simple book that has chapters. """ - name = models.CharField(max_length=100) + name = models.CharField(max_length=100, verbose_name=u'¿Name?') + + def __unicode__(self): + return self.name + +class Promo(models.Model): + name = models.CharField(max_length=100, verbose_name=u'¿Name?') + book = models.ForeignKey(Book) + + def __unicode__(self): + return self.name class Chapter(models.Model): - title = models.CharField(max_length=100) + title = models.CharField(max_length=100, verbose_name=u'¿Title?') content = models.TextField() book = models.ForeignKey(Book) def __unicode__(self): return self.title + class Meta: + verbose_name = u'¿Chapter?' + +class ChapterXtra1(models.Model): + chap = models.OneToOneField(Chapter, verbose_name=u'¿Chap?') + xtra = models.CharField(max_length=100, verbose_name=u'¿Xtra?') + + def __unicode__(self): + return u'¿Xtra1: %s' % self.xtra + +class ChapterXtra2(models.Model): + chap = models.OneToOneField(Chapter, verbose_name=u'¿Chap?') + xtra = models.CharField(max_length=100, verbose_name=u'¿Xtra?') + + def __unicode__(self): + return u'¿Xtra2: %s' % self.xtra + def callable_year(dt_value): return dt_value.year callable_year.admin_order_field = 'date' @@ -109,7 +137,19 @@ class ThingAdmin(admin.ModelAdmin): admin.site.register(Article, ArticleAdmin) admin.site.register(CustomArticle, CustomArticleAdmin) admin.site.register(Section, inlines=[ArticleInline]) -admin.site.register(Book, inlines=[ChapterInline]) admin.site.register(ModelWithStringPrimaryKey) admin.site.register(Color) admin.site.register(Thing, ThingAdmin) + +# We intentionally register Promo and ChapterXtra1 but not Chapter nor ChapterXtra2. +# That way we cover all four cases: +# related ForeignKey object registered in admin +# related ForeignKey object not registered in admin +# related OneToOne object registered in admin +# related OneToOne object not registered in admin +# when deleting Book so as exercise all four troublesome (w.r.t escaping +# and calling force_unicode to avoid problems on Python 2.3) paths through +# contrib.admin.util's get_deleted_objects function. +admin.site.register(Book, inlines=[ChapterInline]) +admin.site.register(Promo) +admin.site.register(ChapterXtra1)