summaryrefslogtreecommitdiff
path: root/django
diff options
context:
space:
mode:
authorJulien Phalip <jphalip@gmail.com>2013-09-07 11:52:14 -0500
committerJulien Phalip <jphalip@gmail.com>2013-09-07 12:14:07 -0500
commit55a11683f7b094ae4fd0b9fa030d18a12657ba98 (patch)
treed40eb5bca9ffdfb9995419bbd74ce0f77f42a3a7 /django
parent4e784f337c4f8ec14e8ea3615fe79f033699e348 (diff)
Fixed #20836 -- Ensure that the ForeignKey's to_field attribute is properly considered by the admin's interface when creating related objects.
Many thanks to Collin Anderson for the report and patch and to Peter Sheats for the test.
Diffstat (limited to 'django')
-rw-r--r--django/contrib/admin/options.py18
-rw-r--r--django/contrib/admin/templates/admin/change_form.html3
-rw-r--r--django/contrib/admin/templates/admin/change_list.html2
-rw-r--r--django/contrib/admin/templates/admin/popup_response.html2
-rw-r--r--django/contrib/admin/templatetags/admin_urls.py5
-rw-r--r--django/contrib/admin/views/main.py3
-rw-r--r--django/contrib/admin/widgets.py6
7 files changed, 29 insertions, 10 deletions
diff --git a/django/contrib/admin/options.py b/django/contrib/admin/options.py
index 72c3635b52..f53d655bfc 100644
--- a/django/contrib/admin/options.py
+++ b/django/contrib/admin/options.py
@@ -44,6 +44,7 @@ from django.views.decorators.csrf import csrf_protect
IS_POPUP_VAR = '_popup'
+TO_FIELD_VAR = '_to_field'
HORIZONTAL, VERTICAL = 1, 2
# returns the <ul> class for a given radio_admin field
@@ -932,6 +933,8 @@ class ModelAdmin(BaseModelAdmin):
'content_type_id': ContentType.objects.get_for_model(self.model).id,
'save_as': self.save_as,
'save_on_top': self.save_on_top,
+ 'to_field_var': TO_FIELD_VAR,
+ 'is_popup_var': IS_POPUP_VAR
})
if add and self.add_form_template is not None:
form_template = self.add_form_template
@@ -951,13 +954,20 @@ class ModelAdmin(BaseModelAdmin):
opts = obj._meta
pk_value = obj._get_pk_val()
preserved_filters = self.get_preserved_filters(request)
-
msg_dict = {'name': force_text(opts.verbose_name), 'obj': force_text(obj)}
# Here, we distinguish between different save types by checking for
# the presence of keys in request.POST.
+
if IS_POPUP_VAR in request.POST:
+ to_field = request.POST.get(TO_FIELD_VAR)
+ if to_field:
+ attr = str(to_field)
+ else:
+ attr = obj._meta.pk.attname
+ value = obj.serializable_value(attr)
return SimpleTemplateResponse('admin/popup_response.html', {
- 'pk_value': escape(pk_value),
+ 'pk_value': escape(pk_value), # for possible backwards-compatibility
+ 'value': escape(value),
'obj': escapejs(obj)
})
@@ -988,6 +998,7 @@ class ModelAdmin(BaseModelAdmin):
"""
Determines the HttpResponse for the change_view stage.
"""
+
opts = self.model._meta
pk_value = obj._get_pk_val()
preserved_filters = self.get_preserved_filters(request)
@@ -1224,6 +1235,7 @@ class ModelAdmin(BaseModelAdmin):
title=_('Add %s') % force_text(opts.verbose_name),
adminform=adminForm,
is_popup=IS_POPUP_VAR in request.REQUEST,
+ to_field=request.REQUEST.get(TO_FIELD_VAR),
media=media,
inline_admin_formsets=inline_admin_formsets,
errors=helpers.AdminErrorList(form, formsets),
@@ -1297,6 +1309,7 @@ class ModelAdmin(BaseModelAdmin):
object_id=object_id,
original=obj,
is_popup=IS_POPUP_VAR in request.REQUEST,
+ to_field=request.REQUEST.get(TO_FIELD_VAR),
media=media,
inline_admin_formsets=inline_admin_formsets,
errors=helpers.AdminErrorList(form, formsets),
@@ -1443,6 +1456,7 @@ class ModelAdmin(BaseModelAdmin):
selection_note_all=selection_note_all % {'total_count': cl.result_count},
title=cl.title,
is_popup=cl.is_popup,
+ to_field=cl.to_field,
cl=cl,
media=media,
has_add_permission=self.has_add_permission(request),
diff --git a/django/contrib/admin/templates/admin/change_form.html b/django/contrib/admin/templates/admin/change_form.html
index c6969f6cc8..1acfcd37db 100644
--- a/django/contrib/admin/templates/admin/change_form.html
+++ b/django/contrib/admin/templates/admin/change_form.html
@@ -39,7 +39,8 @@
{% endblock %}
<form {% if has_file_field %}enctype="multipart/form-data" {% endif %}action="{{ form_url }}" method="post" id="{{ opts.model_name }}_form">{% csrf_token %}{% block form_top %}{% endblock %}
<div>
-{% if is_popup %}<input type="hidden" name="_popup" value="1" />{% endif %}
+{% if is_popup %}<input type="hidden" name="{{ is_popup_var }}" value="1" />{% endif %}
+{% if to_field %}<input type="hidden" name="{{ to_field_var }}" value="{{ to_field }}" />{% endif %}
{% if save_on_top %}{% block submit_buttons_top %}{% submit_row %}{% endblock %}{% endif %}
{% if errors %}
<p class="errornote">
diff --git a/django/contrib/admin/templates/admin/change_list.html b/django/contrib/admin/templates/admin/change_list.html
index ce5c5b37a4..a5a31f9c67 100644
--- a/django/contrib/admin/templates/admin/change_list.html
+++ b/django/contrib/admin/templates/admin/change_list.html
@@ -54,7 +54,7 @@
{% block object-tools-items %}
<li>
{% url cl.opts|admin_urlname:'add' as add_url %}
- <a href="{% add_preserved_filters add_url is_popup %}" class="addlink">
+ <a href="{% add_preserved_filters add_url is_popup to_field %}" class="addlink">
{% blocktrans with cl.opts.verbose_name as name %}Add {{ name }}{% endblocktrans %}
</a>
</li>
diff --git a/django/contrib/admin/templates/admin/popup_response.html b/django/contrib/admin/templates/admin/popup_response.html
index 44833b2f93..281f0354ee 100644
--- a/django/contrib/admin/templates/admin/popup_response.html
+++ b/django/contrib/admin/templates/admin/popup_response.html
@@ -3,7 +3,7 @@
<head><title></title></head>
<body>
<script type="text/javascript">
- opener.dismissAddAnotherPopup(window, "{{ pk_value }}", "{{ obj }}");
+ opener.dismissAddAnotherPopup(window, "{{ value }}", "{{ obj }}");
</script>
</body>
</html>
diff --git a/django/contrib/admin/templatetags/admin_urls.py b/django/contrib/admin/templatetags/admin_urls.py
index 5d9c5b5427..fd45bf306a 100644
--- a/django/contrib/admin/templatetags/admin_urls.py
+++ b/django/contrib/admin/templatetags/admin_urls.py
@@ -22,7 +22,7 @@ def admin_urlquote(value):
@register.simple_tag(takes_context=True)
-def add_preserved_filters(context, url, popup=False):
+def add_preserved_filters(context, url, popup=False, to_field=None):
opts = context.get('opts')
preserved_filters = context.get('preserved_filters')
@@ -48,6 +48,9 @@ def add_preserved_filters(context, url, popup=False):
if popup:
from django.contrib.admin.options import IS_POPUP_VAR
merged_qs[IS_POPUP_VAR] = 1
+ if to_field:
+ from django.contrib.admin.options import TO_FIELD_VAR
+ merged_qs[TO_FIELD_VAR] = to_field
merged_qs.update(parsed_qs)
diff --git a/django/contrib/admin/views/main.py b/django/contrib/admin/views/main.py
index 3325747a9f..14f7655251 100644
--- a/django/contrib/admin/views/main.py
+++ b/django/contrib/admin/views/main.py
@@ -15,7 +15,7 @@ from django.utils.http import urlencode
from django.contrib.admin import FieldListFilter
from django.contrib.admin.exceptions import DisallowedModelAdminLookup
-from django.contrib.admin.options import IncorrectLookupParameters, IS_POPUP_VAR
+from django.contrib.admin.options import IncorrectLookupParameters, IS_POPUP_VAR, TO_FIELD_VAR
from django.contrib.admin.util import (quote, get_fields_from_path,
lookup_needs_distinct, prepare_lookup_value)
@@ -25,7 +25,6 @@ ORDER_VAR = 'o'
ORDER_TYPE_VAR = 'ot'
PAGE_VAR = 'p'
SEARCH_VAR = 'q'
-TO_FIELD_VAR = 't'
ERROR_FLAG = 'e'
IGNORED_PARAMS = (
diff --git a/django/contrib/admin/widgets.py b/django/contrib/admin/widgets.py
index e5b590e0d0..fe6c9e13a9 100644
--- a/django/contrib/admin/widgets.py
+++ b/django/contrib/admin/widgets.py
@@ -248,16 +248,18 @@ class RelatedFieldWidgetWrapper(forms.Widget):
return self.widget.media
def render(self, name, value, *args, **kwargs):
+ from django.contrib.admin.views.main import TO_FIELD_VAR
rel_to = self.rel.to
info = (rel_to._meta.app_label, rel_to._meta.model_name)
self.widget.choices = self.choices
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)
+ url_params = '?%s=%s' % (TO_FIELD_VAR, self.rel.get_related_field().name)
# TODO: "add_id_" is hard-coded here. This should instead use the
# correct API to determine the ID dynamically.
- output.append('<a href="%s" class="add-another" id="add_id_%s" onclick="return showAddAnotherPopup(this);"> '
- % (related_url, name))
+ output.append('<a href="%s%s" class="add-another" id="add_id_%s" onclick="return showAddAnotherPopup(this);"> '
+ % (related_url, url_params, name))
output.append('<img src="%s" width="10" height="10" alt="%s"/></a>'
% (static('admin/img/icon_addlink.gif'), _('Add Another')))
return mark_safe(''.join(output))