Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

[1.1.X] Fixed #12561. InlineAdmin now respects can_delete=False. Back…

…port of [12533] from trunk.

git-svn-id: http://code.djangoproject.com/svn/django/branches/releases/1.1.X@12534 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information...
commit 651082267956cef3bf3dbd48c5314046c14ca01c 1 parent c7117b1
Joseph Kocherhans authored February 23, 2010
2  AUTHORS
@@ -68,7 +68,7 @@ answer newbie questions, and generally made Django that much better:
68 68
     James Bennett
69 69
     Julian Bez
70 70
     Arvis Bickovskis <viestards.lists@gmail.com>
71  
-    Natalia Bidart
  71
+    Natalia Bidart <nataliabidart@gmail.com>
72 72
     Paul Bissex <http://e-scribe.com/>
73 73
     Simon Blanchard
74 74
     David Blewett <david@dawninglight.net>
2  django/contrib/admin/options.py
@@ -1121,6 +1121,7 @@ class InlineModelAdmin(BaseModelAdmin):
1121 1121
     template = None
1122 1122
     verbose_name = None
1123 1123
     verbose_name_plural = None
  1124
+    can_delete = True
1124 1125
 
1125 1126
     def __init__(self, parent_model, admin_site):
1126 1127
         self.admin_site = admin_site
@@ -1163,6 +1164,7 @@ def get_formset(self, request, obj=None, **kwargs):
1163 1164
             "formfield_callback": curry(self.formfield_for_dbfield, request=request),
1164 1165
             "extra": self.extra,
1165 1166
             "max_num": self.max_num,
  1167
+            "can_delete": self.can_delete,
1166 1168
         }
1167 1169
         defaults.update(kwargs)
1168 1170
         return inlineformset_factory(self.parent_model, self.model, **defaults)
2  django/contrib/contenttypes/generic.py
@@ -386,7 +386,7 @@ def get_formset(self, request, obj=None):
386 386
             "formfield_callback": self.formfield_for_dbfield,
387 387
             "formset": self.formset,
388 388
             "extra": self.extra,
389  
-            "can_delete": True,
  389
+            "can_delete": self.can_delete,
390 390
             "can_order": False,
391 391
             "fields": fields,
392 392
             "max_num": self.max_num,
17  tests/regressiontests/admin_inlines/fixtures/admin-views-users.xml
... ...
@@ -0,0 +1,17 @@
  1
+<?xml version="1.0" encoding="utf-8"?>
  2
+<django-objects version="1.0">
  3
+    <object pk="100" model="auth.user">
  4
+        <field type="CharField" name="username">super</field>
  5
+        <field type="CharField" name="first_name">Super</field>
  6
+        <field type="CharField" name="last_name">User</field>
  7
+        <field type="CharField" name="email">super@example.com</field>
  8
+        <field type="CharField" name="password">sha1$995a3$6011485ea3834267d719b4c801409b8b1ddd0158</field>
  9
+        <field type="BooleanField" name="is_staff">True</field>
  10
+        <field type="BooleanField" name="is_active">True</field>
  11
+        <field type="BooleanField" name="is_superuser">True</field>
  12
+        <field type="DateTimeField" name="last_login">2007-05-30 13:20:10</field>
  13
+        <field type="DateTimeField" name="date_joined">2007-05-30 13:20:10</field>
  14
+        <field to="auth.group" name="groups" rel="ManyToManyRel"></field>
  15
+        <field to="auth.permission" name="user_permissions" rel="ManyToManyRel"></field>
  16
+    </object>
  17
+</django-objects>
21  tests/regressiontests/admin_inlines/models.py
@@ -3,6 +3,7 @@
3 3
 
4 4
 """
5 5
 from django.db import models
  6
+from django.contrib import admin
6 7
 from django.contrib.contenttypes.models import ContentType
7 8
 from django.contrib.contenttypes import generic
8 9
 
@@ -29,6 +30,24 @@ class Child(models.Model):
29 30
     def __unicode__(self):
30 31
         return u'I am %s, a child of %s' % (self.name, self.parent)
31 32
 
  33
+
  34
+class Holder(models.Model):
  35
+    dummy = models.IntegerField()
  36
+
  37
+
  38
+class Inner(models.Model):
  39
+    dummy = models.IntegerField()
  40
+    holder = models.ForeignKey(Holder)
  41
+
  42
+
  43
+class InnerInline(admin.StackedInline):
  44
+    model = Inner
  45
+    can_delete = False
  46
+
  47
+
  48
+# Test bug #12561
  49
+admin.site.register(Holder, inlines=[InnerInline])
  50
+
32 51
 __test__ = {'API_TESTS': """
33 52
 
34 53
 # Regression test for #9362
@@ -48,4 +67,4 @@ def __unicode__(self):
48 67
 <Child: I am Joe, a child of John>
49 68
 
50 69
 """
51  
-}
  70
+}
30  tests/regressiontests/admin_inlines/tests.py
... ...
@@ -0,0 +1,30 @@
  1
+from django.test import TestCase
  2
+
  3
+# local test models
  4
+from models import Holder, Inner, InnerInline
  5
+
  6
+class TestInline(TestCase):
  7
+    fixtures = ['admin-views-users.xml']
  8
+
  9
+    def setUp(self):
  10
+        holder = Holder(dummy=13)
  11
+        holder.save()
  12
+        Inner(dummy=42, holder=holder).save()
  13
+        self.change_url = '/test_admin/admin/admin_inlines/holder/%i/' % holder.id
  14
+
  15
+        result = self.client.login(username='super', password='secret')
  16
+        self.failUnlessEqual(result, True)
  17
+
  18
+    def tearDown(self):
  19
+        self.client.logout()
  20
+
  21
+    def test_can_delete(self):
  22
+        """
  23
+        can_delete should be passed to inlineformset factory.
  24
+        """
  25
+        response = self.client.get(self.change_url)
  26
+        inner_formset = response.context[-1]['inline_admin_formsets'][0].formset
  27
+        expected = InnerInline.can_delete
  28
+        actual = inner_formset.can_delete
  29
+        self.assertEqual(expected, actual, 'can_delete must be equal')
  30
+
12  tests/regressiontests/generic_inline_admin/models.py
@@ -72,3 +72,15 @@ class MediaExcludeInline(generic.GenericTabularInline):
72 72
 
73 73
 admin.site.register(EpisodeExclude, inlines=[MediaExcludeInline])
74 74
 
  75
+#
  76
+# Generic inline with can_delete=False
  77
+#
  78
+
  79
+class EpisodePermanent(Episode):
  80
+    pass
  81
+
  82
+class MediaPermanentInline(generic.GenericTabularInline):
  83
+    model = Media
  84
+    can_delete = False
  85
+
  86
+admin.site.register(EpisodePermanent, inlines=[MediaPermanentInline])
11  tests/regressiontests/generic_inline_admin/tests.py
@@ -5,7 +5,8 @@
5 5
 from django.contrib.contenttypes.generic import generic_inlineformset_factory
6 6
 
7 7
 # local test models
8  
-from models import Episode, EpisodeExtra, EpisodeMaxNum, EpisodeExclude, Media
  8
+from models import Episode, EpisodeExtra, EpisodeMaxNum, EpisodeExclude, \
  9
+                   Media, EpisodePermanent, MediaPermanentInline
9 10
 
10 11
 class GenericAdminViewTest(TestCase):
11 12
     fixtures = ['users.xml']
@@ -177,3 +178,11 @@ def testExcludeParam(self):
177 178
         response = self.client.get('/generic_inline_admin/admin/generic_inline_admin/episodeexclude/%s/' % e.pk)
178 179
         formset = response.context['inline_admin_formsets'][0].formset
179 180
         self.failIf('url' in formset.forms[0], 'The formset has excluded "url" field.')
  181
+
  182
+class NoInlineDeletionTest(TestCase):
  183
+    def test_no_deletion(self):
  184
+        fake_site = object()
  185
+        inline = MediaPermanentInline(EpisodePermanent, fake_site)
  186
+        fake_request = object()
  187
+        formset = inline.get_formset(fake_request)
  188
+        self.assertFalse(formset.can_delete)
1  tests/regressiontests/modeladmin/models.py
@@ -291,6 +291,7 @@ class and an AdminSite instance, so let's just go ahead and do that manually
291 291
 ...     form = AdminConcertForm
292 292
 ...     model = Concert
293 293
 ...     fk_name = 'main_band'
  294
+...     can_delete = True
294 295
 
295 296
 >>> class BandAdmin(ModelAdmin):
296 297
 ...     inlines = [

0 notes on commit 6510822

Please sign in to comment.
Something went wrong with that request. Please try again.