mirror of https://github.com/django/django.git
Fixed #11639, #13618 -- Added get_prepopulated_fields method to ModelAdmin and InlineModelAdmin to be able to handle prepopulated fields on a case-by-case basis. Thanks, leanmeandonothingmachine.
git-svn-id: http://code.djangoproject.com/svn/django/trunk@16069 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
51cfd7a50b
commit
6c17190bf8
|
@ -193,7 +193,8 @@ class InlineAdminFormSet(object):
|
|||
"""
|
||||
A wrapper around an inline formset for use in the admin system.
|
||||
"""
|
||||
def __init__(self, inline, formset, fieldsets, readonly_fields=None, model_admin=None):
|
||||
def __init__(self, inline, formset, fieldsets, prepopulated_fields=None,
|
||||
readonly_fields=None, model_admin=None):
|
||||
self.opts = inline
|
||||
self.formset = formset
|
||||
self.fieldsets = fieldsets
|
||||
|
@ -201,18 +202,21 @@ class InlineAdminFormSet(object):
|
|||
if readonly_fields is None:
|
||||
readonly_fields = ()
|
||||
self.readonly_fields = readonly_fields
|
||||
if prepopulated_fields is None:
|
||||
prepopulated_fields = {}
|
||||
self.prepopulated_fields = prepopulated_fields
|
||||
|
||||
def __iter__(self):
|
||||
for form, original in zip(self.formset.initial_forms, self.formset.get_queryset()):
|
||||
yield InlineAdminForm(self.formset, form, self.fieldsets,
|
||||
self.opts.prepopulated_fields, original, self.readonly_fields,
|
||||
self.prepopulated_fields, original, self.readonly_fields,
|
||||
model_admin=self.opts)
|
||||
for form in self.formset.extra_forms:
|
||||
yield InlineAdminForm(self.formset, form, self.fieldsets,
|
||||
self.opts.prepopulated_fields, None, self.readonly_fields,
|
||||
self.prepopulated_fields, None, self.readonly_fields,
|
||||
model_admin=self.opts)
|
||||
yield InlineAdminForm(self.formset, self.formset.empty_form,
|
||||
self.fieldsets, self.opts.prepopulated_fields, None,
|
||||
self.fieldsets, self.prepopulated_fields, None,
|
||||
self.readonly_fields, model_admin=self.opts)
|
||||
|
||||
def fields(self):
|
||||
|
|
|
@ -189,8 +189,17 @@ class BaseModelAdmin(object):
|
|||
declared_fieldsets = property(_declared_fieldsets)
|
||||
|
||||
def get_readonly_fields(self, request, obj=None):
|
||||
"""
|
||||
Hook for specifying custom readonly fields.
|
||||
"""
|
||||
return self.readonly_fields
|
||||
|
||||
def get_prepopulated_fields(self, request, obj=None):
|
||||
"""
|
||||
Hook for specifying custom prepopulated fields.
|
||||
"""
|
||||
return self.prepopulated_fields
|
||||
|
||||
def queryset(self, request):
|
||||
"""
|
||||
Returns a QuerySet of all model instances that can be edited by the
|
||||
|
@ -909,7 +918,8 @@ class ModelAdmin(BaseModelAdmin):
|
|||
formsets.append(formset)
|
||||
|
||||
adminForm = helpers.AdminForm(form, list(self.get_fieldsets(request)),
|
||||
self.prepopulated_fields, self.get_readonly_fields(request),
|
||||
self.get_prepopulated_fields(request),
|
||||
self.get_readonly_fields(request),
|
||||
model_admin=self)
|
||||
media = self.media + adminForm.media
|
||||
|
||||
|
@ -917,8 +927,9 @@ class ModelAdmin(BaseModelAdmin):
|
|||
for inline, formset in zip(self.inline_instances, formsets):
|
||||
fieldsets = list(inline.get_fieldsets(request))
|
||||
readonly = list(inline.get_readonly_fields(request))
|
||||
prepopulated = dict(inline.get_prepopulated_fields(request))
|
||||
inline_admin_formset = helpers.InlineAdminFormSet(inline, formset,
|
||||
fieldsets, readonly, model_admin=self)
|
||||
fieldsets, prepopulated, readonly, model_admin=self)
|
||||
inline_admin_formsets.append(inline_admin_formset)
|
||||
media = media + inline_admin_formset.media
|
||||
|
||||
|
@ -1000,7 +1011,8 @@ class ModelAdmin(BaseModelAdmin):
|
|||
formsets.append(formset)
|
||||
|
||||
adminForm = helpers.AdminForm(form, self.get_fieldsets(request, obj),
|
||||
self.prepopulated_fields, self.get_readonly_fields(request, obj),
|
||||
self.get_prepopulated_fields(request, obj),
|
||||
self.get_readonly_fields(request, obj),
|
||||
model_admin=self)
|
||||
media = self.media + adminForm.media
|
||||
|
||||
|
@ -1008,8 +1020,9 @@ class ModelAdmin(BaseModelAdmin):
|
|||
for inline, formset in zip(self.inline_instances, formsets):
|
||||
fieldsets = list(inline.get_fieldsets(request, obj))
|
||||
readonly = list(inline.get_readonly_fields(request, obj))
|
||||
prepopulated = dict(inline.get_prepopulated_fields(request, obj))
|
||||
inline_admin_formset = helpers.InlineAdminFormSet(inline, formset,
|
||||
fieldsets, readonly, model_admin=self)
|
||||
fieldsets, prepopulated, readonly, model_admin=self)
|
||||
inline_admin_formsets.append(inline_admin_formset)
|
||||
media = media + inline_admin_formset.media
|
||||
|
||||
|
|
|
@ -839,6 +839,15 @@ templates used by the :class:`ModelAdmin` views:
|
|||
a ``list`` or ``tuple`` of field names that will be displayed as read-only,
|
||||
as described above in the :attr:`ModelAdmin.readonly_fields` section.
|
||||
|
||||
.. method:: ModelAdmin.get_prepopulated_fields(self, request, obj=None)
|
||||
|
||||
.. versionadded:: 1.4
|
||||
|
||||
The ``get_prepopulated_fields`` method is given the ``HttpRequest`` and the
|
||||
``obj`` being edited (or ``None`` on an add form) and is expected to return
|
||||
a ``dictionary``, as described above in the :attr:`ModelAdmin.prepopulated_fields`
|
||||
section.
|
||||
|
||||
.. method:: ModelAdmin.get_urls(self)
|
||||
|
||||
The ``get_urls`` method on a ``ModelAdmin`` returns the URLs to be used for
|
||||
|
|
|
@ -88,6 +88,9 @@
|
|||
<field type="DateTimeField" name="date">2009-03-18 11:54:58</field>
|
||||
<field to="admin_views.section" name="section" rel="ManyToOneRel">1</field>
|
||||
</object>
|
||||
|
||||
|
||||
</django-objects>
|
||||
<object pk="1" model="admin_views.prepopulatedpost">
|
||||
<field type="TextField" name="title">A Long Title</field>
|
||||
<field type="BooleanField" name="published">True</field>
|
||||
<field type="SlugField" name="slug">a-long-title</field>
|
||||
</object>
|
||||
</django-objects>
|
||||
|
|
|
@ -529,6 +529,51 @@ class LinkInline(admin.TabularInline):
|
|||
readonly_fields = ("posted",)
|
||||
|
||||
|
||||
class PrePopulatedPost(models.Model):
|
||||
title = models.CharField(max_length=100)
|
||||
published = models.BooleanField()
|
||||
slug = models.SlugField()
|
||||
|
||||
class PrePopulatedSubPost(models.Model):
|
||||
post = models.ForeignKey(PrePopulatedPost)
|
||||
subtitle = models.CharField(max_length=100)
|
||||
subslug = models.SlugField()
|
||||
|
||||
class SubPostInline(admin.TabularInline):
|
||||
model = PrePopulatedSubPost
|
||||
|
||||
prepopulated_fields = {
|
||||
'subslug' : ('subtitle',)
|
||||
}
|
||||
|
||||
def get_readonly_fields(self, request, obj=None):
|
||||
if obj and obj.published:
|
||||
return ('subslug',)
|
||||
return self.readonly_fields
|
||||
|
||||
def get_prepopulated_fields(self, request, obj=None):
|
||||
if obj and obj.published:
|
||||
return {}
|
||||
return self.prepopulated_fields
|
||||
|
||||
class PrePopulatedPostAdmin(admin.ModelAdmin):
|
||||
list_display = ['title', 'slug']
|
||||
prepopulated_fields = {
|
||||
'slug' : ('title',)
|
||||
}
|
||||
|
||||
inlines = [SubPostInline]
|
||||
|
||||
def get_readonly_fields(self, request, obj=None):
|
||||
if obj and obj.published:
|
||||
return ('slug',)
|
||||
return self.readonly_fields
|
||||
|
||||
def get_prepopulated_fields(self, request, obj=None):
|
||||
if obj and obj.published:
|
||||
return {}
|
||||
return self.prepopulated_fields
|
||||
|
||||
class Post(models.Model):
|
||||
title = models.CharField(max_length=100, help_text="Some help text for the title (with unicode ŠĐĆŽćžšđ)")
|
||||
content = models.TextField(help_text="Some help text for the content (with unicode ŠĐĆŽćžšđ)")
|
||||
|
@ -818,3 +863,4 @@ admin.site.register(Topping)
|
|||
admin.site.register(Album, AlbumAdmin)
|
||||
admin.site.register(Question)
|
||||
admin.site.register(Answer)
|
||||
admin.site.register(PrePopulatedPost, PrePopulatedPostAdmin)
|
||||
|
|
|
@ -2579,6 +2579,30 @@ class NeverCacheTests(TestCase):
|
|||
self.assertEqual(get_max_age(response), None)
|
||||
|
||||
|
||||
class PrePopulatedTest(TestCase):
|
||||
fixtures = ['admin-views-users.xml']
|
||||
|
||||
def setUp(self):
|
||||
self.client.login(username='super', password='secret')
|
||||
|
||||
def tearDown(self):
|
||||
self.client.logout()
|
||||
|
||||
def test_prepopulated_on(self):
|
||||
response = self.client.get('/test_admin/admin/admin_views/prepopulatedpost/add/')
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertContains(response, "id: '#id_slug',")
|
||||
self.assertContains(response, "field['dependency_ids'].push('#id_title');")
|
||||
self.assertContains(response, "id: '#id_prepopulatedsubpost_set-0-subslug',")
|
||||
|
||||
def test_prepopulated_off(self):
|
||||
response = self.client.get('/test_admin/admin/admin_views/prepopulatedpost/1/')
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertContains(response, "A Long Title")
|
||||
self.assertNotContains(response, "id: '#id_slug'")
|
||||
self.assertNotContains(response, "field['dependency_ids'].push('#id_title');")
|
||||
self.assertNotContains(response, "id: '#id_prepopulatedsubpost_set-0-subslug',")
|
||||
|
||||
class ReadonlyTest(TestCase):
|
||||
fixtures = ['admin-views-users.xml']
|
||||
|
||||
|
|
Loading…
Reference in New Issue