summaryrefslogtreecommitdiff
path: root/django
diff options
context:
space:
mode:
authorRamiro Morales <cramm0@gmail.com>2011-08-01 23:38:11 +0000
committerRamiro Morales <cramm0@gmail.com>2011-08-01 23:38:11 +0000
commit290d7d4d21692336aeb074917acbf9804275fbdd (patch)
treee456e89bb528f6ec957764d337bc66243586f329 /django
parent56775c23eebf63495f86d41c93c60e9bc80d1ff3 (diff)
Fixed #16542 -- Made Raw ID form widgets shipped with the admin app render the related object lookup tool only when the related model is effectively registered with the AdminSite.
Also, converted these widgets to reverse named URLs instead of hard-coded '../../...'-style links, refs #15294. Thanks Florian Apolloner for the initial patch. git-svn-id: http://code.djangoproject.com/svn/django/trunk@16578 bcc190cf-cafb-0310-a4f2-bffc1f526a37
Diffstat (limited to 'django')
-rw-r--r--django/contrib/admin/options.py6
-rw-r--r--django/contrib/admin/widgets.py51
2 files changed, 35 insertions, 22 deletions
diff --git a/django/contrib/admin/options.py b/django/contrib/admin/options.py
index b0eb113359..35c3cde0fc 100644
--- a/django/contrib/admin/options.py
+++ b/django/contrib/admin/options.py
@@ -154,7 +154,8 @@ class BaseModelAdmin(object):
"""
db = kwargs.get('using')
if db_field.name in self.raw_id_fields:
- kwargs['widget'] = widgets.ForeignKeyRawIdWidget(db_field.rel, using=db)
+ kwargs['widget'] = widgets.ForeignKeyRawIdWidget(db_field.rel,
+ self.admin_site, using=db)
elif db_field.name in self.radio_fields:
kwargs['widget'] = widgets.AdminRadioSelect(attrs={
'class': get_ul_class(self.radio_fields[db_field.name]),
@@ -174,7 +175,8 @@ class BaseModelAdmin(object):
db = kwargs.get('using')
if db_field.name in self.raw_id_fields:
- kwargs['widget'] = widgets.ManyToManyRawIdWidget(db_field.rel, using=db)
+ kwargs['widget'] = widgets.ManyToManyRawIdWidget(db_field.rel,
+ self.admin_site, using=db)
kwargs['help_text'] = ''
elif db_field.name in (list(self.filter_vertical) + list(self.filter_horizontal)):
kwargs['widget'] = widgets.FilteredSelectMultiple(db_field.verbose_name, (db_field.name in self.filter_vertical))
diff --git a/django/contrib/admin/widgets.py b/django/contrib/admin/widgets.py
index 713ce63831..038351e6da 100644
--- a/django/contrib/admin/widgets.py
+++ b/django/contrib/admin/widgets.py
@@ -4,7 +4,7 @@ Form Widget classes specific to the Django admin site.
import copy
from django import forms
-from django.core.urlresolvers import reverse, NoReverseMatch
+from django.core.urlresolvers import reverse
from django.forms.widgets import RadioFieldRenderer
from django.forms.util import flatatt
from django.templatetags.static import static
@@ -112,29 +112,38 @@ class ForeignKeyRawIdWidget(forms.TextInput):
A Widget for displaying ForeignKeys in the "raw_id" interface rather than
in a <select> box.
"""
- def __init__(self, rel, attrs=None, using=None):
+ def __init__(self, rel, admin_site, attrs=None, using=None):
self.rel = rel
+ self.admin_site = admin_site
self.db = using
super(ForeignKeyRawIdWidget, self).__init__(attrs)
def render(self, name, value, attrs=None):
+ rel_to = self.rel.to
if attrs is None:
attrs = {}
- related_url = '../../../%s/%s/' % (self.rel.to._meta.app_label, self.rel.to._meta.object_name.lower())
- params = self.url_parameters()
- if params:
- url = u'?' + u'&amp;'.join([u'%s=%s' % (k, v) for k, v in params.items()])
- else:
- url = u''
- if "class" not in attrs:
- 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.
- output.append(u'<a href="%s%s" class="related-lookup" id="lookup_id_%s" onclick="return showRelatedObjectLookupPopup(this);"> '
- % (related_url, url, name))
- output.append(u'<img src="%s" width="16" height="16" alt="%s" /></a>'
- % (static('admin/img/selector-search.gif'), _('Lookup')))
+ extra = []
+ if rel_to in self.admin_site._registry:
+ # The related object is registered with the same AdminSite
+ related_url = reverse('admin:%s_%s_changelist' %
+ (rel_to._meta.app_label,
+ rel_to._meta.module_name),
+ current_app=self.admin_site.name)
+
+ params = self.url_parameters()
+ if params:
+ url = u'?' + u'&amp;'.join([u'%s=%s' % (k, v) for k, v in params.items()])
+ else:
+ url = u''
+ if "class" not in attrs:
+ attrs['class'] = 'vForeignKeyRawIdAdminField' # The JavaScript code looks for this hook.
+ # TODO: "lookup_id_" is hard-coded here. This should instead use
+ # the correct API to determine the ID dynamically.
+ extra.append(u'<a href="%s%s" class="related-lookup" id="lookup_id_%s" onclick="return showRelatedObjectLookupPopup(this);"> '
+ % (related_url, url, name))
+ extra.append(u'<img src="%s" width="16" height="16" alt="%s" /></a>'
+ % (static('admin/img/selector-search.gif'), _('Lookup')))
+ output = [super(ForeignKeyRawIdWidget, self).render(name, value, attrs)] + extra
if value:
output.append(self.label_for_value(value))
return mark_safe(u''.join(output))
@@ -164,7 +173,9 @@ class ManyToManyRawIdWidget(ForeignKeyRawIdWidget):
def render(self, name, value, attrs=None):
if attrs is None:
attrs = {}
- attrs['class'] = 'vManyToManyRawIdAdminField'
+ if self.rel.to in self.admin_site._registry:
+ # The related object is registered with the same AdminSite
+ attrs['class'] = 'vManyToManyRawIdAdminField'
if value:
value = ','.join([force_unicode(v) for v in value])
else:
@@ -232,8 +243,8 @@ class RelatedFieldWidgetWrapper(forms.Widget):
output = [self.widget.render(name, value, *args, **kwargs)]
if self.can_add_related:
related_url = reverse('admin:%s_%s_add' % info, current_app=self.admin_site.name)
- # TODO: "id_" is hard-coded here. This should instead use the correct
- # API to determine the ID dynamically.
+ # TODO: "add_id_" is hard-coded here. This should instead use the
+ # correct API to determine the ID dynamically.
output.append(u'<a href="%s" class="add-another" id="add_id_%s" onclick="return showAddAnotherPopup(this);"> '
% (related_url, name))
output.append(u'<img src="%s" width="10" height="10" alt="%s"/></a>'