diff --git a/django/contrib/admin/util.py b/django/contrib/admin/util.py
index 6a585b2..82c577c 100644
|
a
|
b
|
def get_deleted_objects(deleted_objects, perms_needed, user, obj, opts, current_
|
| 57 | 57 | opts_seen = [] |
| 58 | 58 | for related in opts.get_all_related_objects(): |
| 59 | 59 | has_admin = related.model in admin_site._registry |
| 60 | | if related.opts in opts_seen: |
| 61 | | continue |
| 62 | | opts_seen.append(related.opts) |
| 63 | 60 | rel_opts_name = related.get_accessor_name() |
| | 61 | if rel_opts_name in opts_seen: |
| | 62 | continue |
| | 63 | opts_seen.append(rel_opts_name) |
| 64 | 64 | if isinstance(related.field.rel, models.OneToOneRel): |
| 65 | 65 | try: |
| 66 | 66 | sub_obj = getattr(obj, rel_opts_name) |
| … |
… |
def get_deleted_objects(deleted_objects, perms_needed, user, obj, opts, current_
|
| 106 | 106 | perms_needed.add(related.opts.verbose_name) |
| 107 | 107 | for related in opts.get_all_related_many_to_many_objects(): |
| 108 | 108 | has_admin = related.model in admin_site._registry |
| 109 | | if related.opts in opts_seen: |
| 110 | | continue |
| 111 | | opts_seen.append(related.opts) |
| 112 | 109 | rel_opts_name = related.get_accessor_name() |
| | 110 | if rel_opts_name in opts_seen: |
| | 111 | continue |
| | 112 | opts_seen.append(rel_opts_name) |
| 113 | 113 | has_related_objs = False |
| 114 | 114 | |
| 115 | 115 | # related.get_accessor_name() could return None for symmetrical relationships |
diff --git a/tests/regressiontests/admin_views/fixtures/deleted-objects.xml b/tests/regressiontests/admin_views/fixtures/deleted-objects.xml
new file mode 100644
index 0000000..a82cfe1
|
-
|
+
|
|
| | 1 | <?xml version="1.0" encoding="utf-8"?> |
| | 2 | <django-objects version="1.0"> |
| | 3 | <object pk="1" model="admin_views.villain"> |
| | 4 | <field type="CharField" name="name">Adam</field> |
| | 5 | </object> |
| | 6 | <object pk="2" model="admin_views.villain"> |
| | 7 | <field type="CharField" name="name">Sue</field> |
| | 8 | </object> |
| | 9 | <object pk="1" model="admin_views.plot"> |
| | 10 | <field type="CharField" name="name">World Domination</field> |
| | 11 | <field type="ForeignKey" name="team_leader">1</field> |
| | 12 | <field type="ForeignKey" name="contact">2</field> |
| | 13 | </object> |
| | 14 | </django-objects> |
diff --git a/tests/regressiontests/admin_views/models.py b/tests/regressiontests/admin_views/models.py
index a8fc946..97db930 100644
|
a
|
b
|
class ModelWithStringPrimaryKey(models.Model):
|
| 59 | 59 | def __unicode__(self): |
| 60 | 60 | return self.id |
| 61 | 61 | |
| | 62 | class Villain(models.Model): |
| | 63 | name = models.CharField(max_length=100) |
| | 64 | |
| | 65 | def __unicode__(self): |
| | 66 | return self.name |
| | 67 | |
| | 68 | class Plot(models.Model): |
| | 69 | name = models.CharField(max_length=100) |
| | 70 | team_leader = models.ForeignKey(Villain, related_name='lead_plots') |
| | 71 | contact = models.ForeignKey(Villain, related_name='contact_plots') |
| | 72 | |
| | 73 | def __unicode__(self): |
| | 74 | return self.name |
| | 75 | |
| 62 | 76 | admin.site.register(Article, ArticleAdmin) |
| 63 | 77 | admin.site.register(CustomArticle, CustomArticleAdmin) |
| 64 | 78 | admin.site.register(Section) |
| 65 | 79 | admin.site.register(ModelWithStringPrimaryKey) |
| | 80 | admin.site.register(Villain) |
| | 81 | admin.site.register(Plot) |
diff --git a/tests/regressiontests/admin_views/tests.py b/tests/regressiontests/admin_views/tests.py
index c7a8a2e..ebdea4d 100644
|
a
|
b
|
class AdminViewStringPrimaryKeyTest(TestCase):
|
| 363 | 363 | response = self.client.get('/test_admin/admin/admin_views/modelwithstringprimarykey/%s/delete/' % quote(self.pk)) |
| 364 | 364 | should_contain = """<a href="../../%s/">%s</a>""" % (quote(self.pk), escape(self.pk)) |
| 365 | 365 | self.assertContains(response, should_contain) |
| | 366 | |
| | 367 | class AdminViewDeletedObjectsTest(TestCase): |
| | 368 | fixtures = ['admin-views-users.xml', 'deleted-objects.xml'] |
| | 369 | |
| | 370 | def setUp(self): |
| | 371 | self.client.login(username='super', password='secret') |
| | 372 | |
| | 373 | def tearDown(self): |
| | 374 | self.client.logout() |
| | 375 | |
| | 376 | def test_deleted_objects(self): |
| | 377 | should_contain = """<li>Plot: <a href="../../../../admin_views/plot/1/">World Domination</a></li>""" |
| | 378 | response = self.client.get('/test_admin/admin/admin_views/villain/%s/delete/' % quote(1)) |
| | 379 | self.assertContains(response, should_contain) |
| | 380 | response = self.client.get('/test_admin/admin/admin_views/villain/%s/delete/' % quote(2)) |
| | 381 | self.assertContains(response, should_contain) |