mirror of
https://github.com/django/django.git
synced 2025-07-04 17:59:13 +00:00
newforms-admin: Added a custom formfield hook for the admin forms. The first customization is that ManyToManyFields with 'filter_interface' set use a special widget, FilteredSelectMultiple. This removes the need for the old filter_interface_script_maybe admin template tag.
git-svn-id: http://code.djangoproject.com/svn/django/branches/newforms-admin@4391 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
b98f9d0089
commit
8c4c07b5d0
@ -1,5 +1,6 @@
|
|||||||
from django import oldforms, template
|
from django import oldforms, template
|
||||||
from django import newforms as forms
|
from django import newforms as forms
|
||||||
|
from django.contrib.admin import widgets
|
||||||
from django.core.exceptions import ImproperlyConfigured, PermissionDenied
|
from django.core.exceptions import ImproperlyConfigured, PermissionDenied
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.http import Http404, HttpResponse, HttpResponseRedirect
|
from django.http import Http404, HttpResponse, HttpResponseRedirect
|
||||||
@ -195,6 +196,19 @@ class ModelAdmin(object):
|
|||||||
for fs in self.fieldsets(request):
|
for fs in self.fieldsets(request):
|
||||||
yield fs
|
yield fs
|
||||||
|
|
||||||
|
def formfield_for_dbfield(self, db_field, **kwargs):
|
||||||
|
"""
|
||||||
|
Hook for specifying the form Field instance for a given database Field
|
||||||
|
instance.
|
||||||
|
|
||||||
|
If kwargs are given, they're passed to the form Field's constructor.
|
||||||
|
"""
|
||||||
|
# For filter_interface ManyToManyFields, use a special Widget.
|
||||||
|
if isinstance(db_field, models.ManyToManyField) and db_field.rel.filter_interface:
|
||||||
|
widget = widgets.FilteredSelectMultiple(db_field.verbose_name, db_field.rel.filter_interface-1)
|
||||||
|
return db_field.formfield(widget=widget)
|
||||||
|
return db_field.formfield(**kwargs)
|
||||||
|
|
||||||
def has_add_permission(self, request):
|
def has_add_permission(self, request):
|
||||||
"Returns True if the given request has permission to add an object."
|
"Returns True if the given request has permission to add an object."
|
||||||
opts = self.opts
|
opts = self.opts
|
||||||
@ -238,7 +252,7 @@ class ModelAdmin(object):
|
|||||||
# Object list will give 'Permission Denied', so go back to admin home
|
# Object list will give 'Permission Denied', so go back to admin home
|
||||||
post_url = '../../../'
|
post_url = '../../../'
|
||||||
|
|
||||||
ModelForm = forms.form_for_model(model)
|
ModelForm = forms.form_for_model(model, formfield_callback=self.formfield_for_dbfield)
|
||||||
|
|
||||||
if request.POST:
|
if request.POST:
|
||||||
new_data = request.POST.copy()
|
new_data = request.POST.copy()
|
||||||
@ -303,7 +317,7 @@ class ModelAdmin(object):
|
|||||||
except model.DoesNotExist:
|
except model.DoesNotExist:
|
||||||
raise Http404('%s object with primary key %r does not exist' % (model_name, escape(object_id)))
|
raise Http404('%s object with primary key %r does not exist' % (model_name, escape(object_id)))
|
||||||
|
|
||||||
ModelForm = forms.form_for_instance(obj)
|
ModelForm = forms.form_for_instance(obj, formfield_callback=self.formfield_for_dbfield)
|
||||||
|
|
||||||
if request.POST:
|
if request.POST:
|
||||||
new_data = request.POST.copy()
|
new_data = request.POST.copy()
|
||||||
|
@ -160,16 +160,6 @@ def auto_populated_field_script(auto_pop_fields, change = False):
|
|||||||
return ''.join(t)
|
return ''.join(t)
|
||||||
auto_populated_field_script = register.simple_tag(auto_populated_field_script)
|
auto_populated_field_script = register.simple_tag(auto_populated_field_script)
|
||||||
|
|
||||||
def filter_interface_script_maybe(bound_field):
|
|
||||||
f = bound_field.field
|
|
||||||
if f.rel and isinstance(f.rel, models.ManyToManyRel) and f.rel.filter_interface:
|
|
||||||
return '<script type="text/javascript">addEvent(window, "load", function(e) {' \
|
|
||||||
' SelectFilter.init("id_%s", "%s", %s, "%s"); });</script>\n' % (
|
|
||||||
f.name, f.verbose_name.replace('"', '\\"'), f.rel.filter_interface-1, settings.ADMIN_MEDIA_PREFIX)
|
|
||||||
else:
|
|
||||||
return ''
|
|
||||||
filter_interface_script_maybe = register.simple_tag(filter_interface_script_maybe)
|
|
||||||
|
|
||||||
def field_widget(parser, token):
|
def field_widget(parser, token):
|
||||||
bits = token.contents.split()
|
bits = token.contents.split()
|
||||||
if len(bits) != 2:
|
if len(bits) != 2:
|
||||||
|
27
django/contrib/admin/widgets.py
Normal file
27
django/contrib/admin/widgets.py
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
"""
|
||||||
|
Form Widget classes specific to the Django admin site.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from django import newforms as forms
|
||||||
|
|
||||||
|
class FilteredSelectMultiple(forms.SelectMultiple):
|
||||||
|
"""
|
||||||
|
A SelectMultiple with a JavaScript filter interface.
|
||||||
|
|
||||||
|
Note that the resulting JavaScript assumes that the SelectFilter2.js
|
||||||
|
library and its dependencies have been loaded in the HTML page.
|
||||||
|
"""
|
||||||
|
def __init__(self, verbose_name, is_stacked, attrs=None, choices=()):
|
||||||
|
self.verbose_name = verbose_name
|
||||||
|
self.is_stacked = is_stacked
|
||||||
|
super(FilteredSelectMultiple, self).__init__(attrs, choices)
|
||||||
|
|
||||||
|
def render(self, name, value, attrs=None, choices=()):
|
||||||
|
from django.conf import settings
|
||||||
|
output = [super(FilteredSelectMultiple, self).render(name, value, attrs, choices)]
|
||||||
|
output.append('<script type="text/javascript">addEvent(window, "load", function(e) {')
|
||||||
|
# TODO: "id_" is hard-coded here. This should instead use the correct
|
||||||
|
# API to determine the ID dynamically.
|
||||||
|
output.append('SelectFilter.init("id_%s", "%s", %s, "%s"); });</script>\n' % \
|
||||||
|
(name, self.verbose_name.replace('"', '\\"'), int(self.is_stacked), settings.ADMIN_MEDIA_PREFIX))
|
||||||
|
return ''.join(output)
|
Loading…
x
Reference in New Issue
Block a user