Fixed #12561. InlineAdmin now respects can_delete=False. Thanks, nessita.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@12533 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Joseph Kocherhans 2010-02-23 17:14:50 +00:00
parent 10b1871441
commit f2d5582c53
9 changed files with 95 additions and 4 deletions

View File

@ -73,7 +73,7 @@ answer newbie questions, and generally made Django that much better:
James Bennett James Bennett
Julian Bez Julian Bez
Arvis Bickovskis <viestards.lists@gmail.com> Arvis Bickovskis <viestards.lists@gmail.com>
Natalia Bidart Natalia Bidart <nataliabidart@gmail.com>
Paul Bissex <http://e-scribe.com/> Paul Bissex <http://e-scribe.com/>
Simon Blanchard Simon Blanchard
David Blewett <david@dawninglight.net> David Blewett <david@dawninglight.net>

View File

@ -1187,6 +1187,7 @@ class InlineModelAdmin(BaseModelAdmin):
template = None template = None
verbose_name = None verbose_name = None
verbose_name_plural = None verbose_name_plural = None
can_delete = True
def __init__(self, parent_model, admin_site): def __init__(self, parent_model, admin_site):
self.admin_site = admin_site self.admin_site = admin_site
@ -1232,6 +1233,7 @@ class InlineModelAdmin(BaseModelAdmin):
"formfield_callback": curry(self.formfield_for_dbfield, request=request), "formfield_callback": curry(self.formfield_for_dbfield, request=request),
"extra": self.extra, "extra": self.extra,
"max_num": self.max_num, "max_num": self.max_num,
"can_delete": self.can_delete,
} }
defaults.update(kwargs) defaults.update(kwargs)
return inlineformset_factory(self.parent_model, self.model, **defaults) return inlineformset_factory(self.parent_model, self.model, **defaults)

View File

@ -390,7 +390,7 @@ class GenericInlineModelAdmin(InlineModelAdmin):
"formfield_callback": self.formfield_for_dbfield, "formfield_callback": self.formfield_for_dbfield,
"formset": self.formset, "formset": self.formset,
"extra": self.extra, "extra": self.extra,
"can_delete": True, "can_delete": self.can_delete,
"can_order": False, "can_order": False,
"fields": fields, "fields": fields,
"max_num": self.max_num, "max_num": self.max_num,

View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<django-objects version="1.0">
<object pk="100" model="auth.user">
<field type="CharField" name="username">super</field>
<field type="CharField" name="first_name">Super</field>
<field type="CharField" name="last_name">User</field>
<field type="CharField" name="email">super@example.com</field>
<field type="CharField" name="password">sha1$995a3$6011485ea3834267d719b4c801409b8b1ddd0158</field>
<field type="BooleanField" name="is_staff">True</field>
<field type="BooleanField" name="is_active">True</field>
<field type="BooleanField" name="is_superuser">True</field>
<field type="DateTimeField" name="last_login">2007-05-30 13:20:10</field>
<field type="DateTimeField" name="date_joined">2007-05-30 13:20:10</field>
<field to="auth.group" name="groups" rel="ManyToManyRel"></field>
<field to="auth.permission" name="user_permissions" rel="ManyToManyRel"></field>
</object>
</django-objects>

View File

@ -3,6 +3,7 @@ Testing of admin inline formsets.
""" """
from django.db import models from django.db import models
from django.contrib import admin
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
from django.contrib.contenttypes import generic from django.contrib.contenttypes import generic
@ -29,6 +30,24 @@ class Child(models.Model):
def __unicode__(self): def __unicode__(self):
return u'I am %s, a child of %s' % (self.name, self.parent) return u'I am %s, a child of %s' % (self.name, self.parent)
class Holder(models.Model):
dummy = models.IntegerField()
class Inner(models.Model):
dummy = models.IntegerField()
holder = models.ForeignKey(Holder)
class InnerInline(admin.StackedInline):
model = Inner
can_delete = False
# Test bug #12561
admin.site.register(Holder, inlines=[InnerInline])
__test__ = {'API_TESTS': """ __test__ = {'API_TESTS': """
# Regression test for #9362 # Regression test for #9362
@ -48,4 +67,4 @@ inline form.
<Child: I am Joe, a child of John> <Child: I am Joe, a child of John>
""" """
} }

View File

@ -0,0 +1,30 @@
from django.test import TestCase
# local test models
from models import Holder, Inner, InnerInline
class TestInline(TestCase):
fixtures = ['admin-views-users.xml']
def setUp(self):
holder = Holder(dummy=13)
holder.save()
Inner(dummy=42, holder=holder).save()
self.change_url = '/test_admin/admin/admin_inlines/holder/%i/' % holder.id
result = self.client.login(username='super', password='secret')
self.failUnlessEqual(result, True)
def tearDown(self):
self.client.logout()
def test_can_delete(self):
"""
can_delete should be passed to inlineformset factory.
"""
response = self.client.get(self.change_url)
inner_formset = response.context[-1]['inline_admin_formsets'][0].formset
expected = InnerInline.can_delete
actual = inner_formset.can_delete
self.assertEqual(expected, actual, 'can_delete must be equal')

View File

@ -93,3 +93,16 @@ class PhoneNumberInline(generic.GenericTabularInline):
model = PhoneNumber model = PhoneNumber
admin.site.register(Contact, inlines=[PhoneNumberInline]) admin.site.register(Contact, inlines=[PhoneNumberInline])
#
# Generic inline with can_delete=False
#
class EpisodePermanent(Episode):
pass
class MediaPermanentInline(generic.GenericTabularInline):
model = Media
can_delete = False
admin.site.register(EpisodePermanent, inlines=[MediaPermanentInline])

View File

@ -5,7 +5,8 @@ from django.conf import settings
from django.contrib.contenttypes.generic import generic_inlineformset_factory from django.contrib.contenttypes.generic import generic_inlineformset_factory
# local test models # local test models
from models import Episode, EpisodeExtra, EpisodeMaxNum, EpisodeExclude, Media from models import Episode, EpisodeExtra, EpisodeMaxNum, EpisodeExclude, \
Media, EpisodePermanent, MediaPermanentInline
class GenericAdminViewTest(TestCase): class GenericAdminViewTest(TestCase):
fixtures = ['users.xml'] fixtures = ['users.xml']
@ -201,3 +202,11 @@ class GenericInlineAdminWithUniqueTogetherTest(TestCase):
response = self.client.get('/generic_inline_admin/admin/generic_inline_admin/contact/add/') response = self.client.get('/generic_inline_admin/admin/generic_inline_admin/contact/add/')
response = self.client.post('/generic_inline_admin/admin/generic_inline_admin/contact/add/', post_data) response = self.client.post('/generic_inline_admin/admin/generic_inline_admin/contact/add/', post_data)
self.failUnlessEqual(response.status_code, 302) # redirect somewhere self.failUnlessEqual(response.status_code, 302) # redirect somewhere
class NoInlineDeletionTest(TestCase):
def test_no_deletion(self):
fake_site = object()
inline = MediaPermanentInline(EpisodePermanent, fake_site)
fake_request = object()
formset = inline.get_formset(fake_request)
self.assertFalse(formset.can_delete)

View File

@ -291,6 +291,7 @@ blank=True for the model field. Finally, the widget should have the
... form = AdminConcertForm ... form = AdminConcertForm
... model = Concert ... model = Concert
... fk_name = 'main_band' ... fk_name = 'main_band'
... can_delete = True
>>> class BandAdmin(ModelAdmin): >>> class BandAdmin(ModelAdmin):
... inlines = [ ... inlines = [