diff --git a/AUTHORS b/AUTHORS
index c5fdd359ea..456a5cff3f 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -201,6 +201,7 @@ answer newbie questions, and generally made Django that much better:
mattycakes@gmail.com
Jason McBrayer
mccutchen@gmail.com
+ Christian Metts
michael.mcewan@gmail.com
mikko@sorl.net
Slawek Mikula
diff --git a/django/contrib/admin/media/js/admin/RelatedObjectLookups.js b/django/contrib/admin/media/js/admin/RelatedObjectLookups.js
index 5588d72ab8..4d33f9e724 100644
--- a/django/contrib/admin/media/js/admin/RelatedObjectLookups.js
+++ b/django/contrib/admin/media/js/admin/RelatedObjectLookups.js
@@ -19,7 +19,7 @@ function showRelatedObjectLookupPopup(triggeringLink) {
function dismissRelatedLookupPopup(win, chosenId) {
var name = win.name.replace(/___/g, '.');
var elem = document.getElementById(name);
- if (elem.className.indexOf('vRawIdAdminField') != -1 && elem.value) {
+ if (elem.className.indexOf('vManyToManyRawIdAdminField') != -1 && elem.value) {
elem.value += ',' + chosenId;
} else {
document.getElementById(name).value = chosenId;
diff --git a/django/contrib/admin/options.py b/django/contrib/admin/options.py
index 72392f4124..2a38205faa 100644
--- a/django/contrib/admin/options.py
+++ b/django/contrib/admin/options.py
@@ -168,13 +168,17 @@ class BaseModelAdmin(object):
if isinstance(db_field, (models.ForeignKey, models.ManyToManyField)):
if isinstance(db_field, models.ForeignKey) and db_field.name in self.raw_id_fields:
kwargs['widget'] = widgets.ForeignKeyRawIdWidget(db_field.rel)
- return db_field.formfield(**kwargs)
else:
- # Wrap the widget's render() method with a method that adds
- # extra HTML to the end of the rendered output.
- formfield = db_field.formfield(**kwargs)
+ if isinstance(db_field, models.ManyToManyField) and db_field.name in self.raw_id_fields:
+ kwargs['widget'] = widgets.ManyToManyRawIdWidget(db_field.rel)
+ kwargs['help_text'] = ''
+ # Wrap the widget's render() method with a method that adds
+ # extra HTML to the end of the rendered output.
+ formfield = db_field.formfield(**kwargs)
+ # Don't wrap raw_id fields. Their add function is in the popup window.
+ if not db_field.name in self.raw_id_fields:
formfield.widget.render = widgets.RelatedFieldWidgetWrapper(formfield.widget.render, db_field.rel, self.admin_site)
- return formfield
+ return formfield
# For any other type of field, just call its formfield() method.
return db_field.formfield(**kwargs)
diff --git a/django/contrib/admin/widgets.py b/django/contrib/admin/widgets.py
index dd0a95a8b1..99bfdef53d 100644
--- a/django/contrib/admin/widgets.py
+++ b/django/contrib/admin/widgets.py
@@ -3,6 +3,7 @@ Form Widget classes specific to the Django admin site.
"""
from django import newforms as forms
+from django.utils.datastructures import MultiValueDict
from django.utils.text import capfirst
from django.utils.translation import ugettext as _
from django.conf import settings
@@ -75,7 +76,8 @@ class ForeignKeyRawIdWidget(forms.TextInput):
url = '?' + '&'.join(['%s=%s' % (k, v) for k, v in self.rel.limit_choices_to.items()])
else:
url = ''
- attrs['class'] = 'vRawIdAdminField' # The JavaScript looks for this hook.
+ if not attrs.has_key('class'):
+ attrs['class'] = 'vForeignKeyRawIdAdminField' # The JavaScript looks for this hook.
output = [super(ForeignKeyRawIdWidget, self).render(name, value, attrs)]
# TODO: "id_" is hard-coded here. This should instead use the correct
# API to determine the ID dynamically.
@@ -85,6 +87,27 @@ class ForeignKeyRawIdWidget(forms.TextInput):
return u''.join(output)
#if self.change: # TODO
#output.append(' TODO')
+
+class ManyToManyRawIdWidget(ForeignKeyRawIdWidget):
+ """
+ A Widget for displaying ManyToMany ids in the "raw_id" interface rather than
+ in a