diff --git a/django/contrib/admin/options.py b/django/contrib/admin/options.py
index 4d23f8f..5e78bce 100644
--- a/django/contrib/admin/options.py
+++ b/django/contrib/admin/options.py
@@ -776,14 +776,17 @@ class ModelAdmin(BaseModelAdmin):
             self.message_user(request, msg + ' ' + _("You may edit it again below."))
             if "_popup" in request.POST:
                 post_url_continue += "?_popup=1"
+                if '_callback' in request.REQUEST:
+                    post_url_continue += '&_callback=%s' % request.REQUEST.get('_callback')
             return HttpResponseRedirect(post_url_continue % pk_value)
 
         if "_popup" in request.POST:
+            popup_callback = request.REQUEST.get('_callback', 'dismissAddAnotherPopup')
             return HttpResponse(
                 '<!DOCTYPE html><html><head><title></title></head><body>'
-                '<script type="text/javascript">opener.dismissAddAnotherPopup(window, "%s", "%s");</script></body></html>' % \
+                '<script type="text/javascript">opener.%s(window, "%s", "%s");</script></body></html>' % \
                 # escape() calls force_unicode.
-                (escape(pk_value), escapejs(obj)))
+                (popup_callback, escape(pk_value), escapejs(obj)))
         elif "_addanother" in request.POST:
             self.message_user(request, msg + ' ' + (_("You may add another %s below.") % force_unicode(opts.verbose_name)))
             return HttpResponseRedirect(request.path)
@@ -1004,6 +1007,8 @@ class ModelAdmin(BaseModelAdmin):
             'errors': helpers.AdminErrorList(form, formsets),
             'app_label': opts.app_label,
         }
+        if '_callback' in request.REQUEST:
+            context.update({'popup_callback': request.REQUEST.get('_callback')})
         context.update(extra_context or {})
         return self.render_change_form(request, context, form_url=form_url, add=True)
 
@@ -1234,6 +1239,7 @@ class ModelAdmin(BaseModelAdmin):
             'selection_note_all': selection_note_all % {'total_count': cl.result_count},
             'title': cl.title,
             'is_popup': cl.is_popup,
+            'popup_callback': cl.popup_callback,
             '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 82d7296..937f0c1 100644
--- a/django/contrib/admin/templates/admin/change_form.html
+++ b/django/contrib/admin/templates/admin/change_form.html
@@ -37,7 +37,7 @@
 {% endblock %}
 <form {% if has_file_field %}enctype="multipart/form-data" {% endif %}action="{{ form_url }}" method="post" id="{{ opts.module_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="_popup" value="1" />{% if popup_callback %}<input type="hidden" name="_callback" value="{{ popup_callback }}" />{% endif %}{% 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 c72b663..c6b82ca 100644
--- a/django/contrib/admin/templates/admin/change_list.html
+++ b/django/contrib/admin/templates/admin/change_list.html
@@ -54,7 +54,7 @@
         <ul class="object-tools">
           {% block object-tools-items %}
             <li>
-              <a href="{% url cl.opts|admin_urlname:'add' %}{% if is_popup %}?_popup=1{% endif %}" class="addlink">
+              <a href="{% url cl.opts|admin_urlname:'add' %}{% if is_popup %}?_popup=1{% if popup_callback %}&_callback={{ popup_callback }}{% endif %}{% endif %}" class="addlink">
                 {% blocktrans with cl.opts.verbose_name as name %}Add {{ name }}{% endblocktrans %}
               </a>
             </li>
diff --git a/django/contrib/admin/templatetags/admin_list.py b/django/contrib/admin/templatetags/admin_list.py
index 0f15781..92e4878 100644
--- a/django/contrib/admin/templatetags/admin_list.py
+++ b/django/contrib/admin/templatetags/admin_list.py
@@ -228,8 +228,10 @@ def items_for_result(cl, result, form):
                               table_tag,
                               row_class,
                               url,
-                              format_html(' onclick="opener.dismissRelatedLookupPopup(window, {0}); return false;"', result_id)
-                                if cl.is_popup else '',
+                              format_html(
+                                  ' onclick="opener.{0}(window, {1}); return false;"',
+                                  cl.get_popup_callback(), result_id
+                              ) if cl.is_popup else '',
                               result_repr,
                               table_tag)
         else:
diff --git a/django/contrib/admin/views/main.py b/django/contrib/admin/views/main.py
index 85e03f3..ffd351b 100644
--- a/django/contrib/admin/views/main.py
+++ b/django/contrib/admin/views/main.py
@@ -24,9 +24,12 @@ SEARCH_VAR = 'q'
 TO_FIELD_VAR = 't'
 IS_POPUP_VAR = 'pop'
 ERROR_FLAG = 'e'
+POPUP_CALLBACK_VAR = '_callback'
+POPUP_CALLBACK_DEFAULT = 'dismissRelatedLookupPopup'
 
 IGNORED_PARAMS = (
-    ALL_VAR, ORDER_VAR, ORDER_TYPE_VAR, SEARCH_VAR, IS_POPUP_VAR, TO_FIELD_VAR)
+    ALL_VAR, ORDER_VAR, ORDER_TYPE_VAR, SEARCH_VAR, IS_POPUP_VAR, TO_FIELD_VAR,
+    POPUP_CALLBACK_VAR)
 
 # Text to display within change-list table cells if the value is blank.
 EMPTY_CHANGELIST_VALUE = ugettext_lazy('(None)')
@@ -57,6 +60,7 @@ class ChangeList(object):
             self.page_num = 0
         self.show_all = ALL_VAR in request.GET
         self.is_popup = IS_POPUP_VAR in request.GET
+        self.popup_callback = request.REQUEST.get(POPUP_CALLBACK_VAR)
         self.to_field = request.GET.get(TO_FIELD_VAR)
         self.params = dict(request.GET.items())
         if PAGE_VAR in self.params:
@@ -377,3 +381,8 @@ class ChangeList(object):
 
     def url_for_result(self, result):
         return "%s/" % quote(getattr(result, self.pk_attname))
+
+    def get_popup_callback(self):
+        if self.popup_callback is not None:
+            return self.popup_callback
+        return POPUP_CALLBACK_DEFAULT
\ No newline at end of file
diff --git a/tests/regressiontests/admin_related_lookup_popup/__init__.py b/tests/regressiontests/admin_related_lookup_popup/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/tests/regressiontests/admin_related_lookup_popup/models.py b/tests/regressiontests/admin_related_lookup_popup/models.py
new file mode 100644
index 0000000..aa1e83e
--- /dev/null
+++ b/tests/regressiontests/admin_related_lookup_popup/models.py
@@ -0,0 +1,22 @@
+from django.db import models
+from django.contrib import admin
+
+
+__all__ = ['RelatedItem', 'AnotherRelatedItem']
+
+
+class RelatedItem(models.Model):
+    title = models.CharField(max_length=25, blank=True, null=True)
+
+    def __unicode__(self):
+        return self.title
+
+class AnotherRelatedItem(models.Model):
+    title = models.CharField(max_length=15, blank=True, null=True)
+
+    def __unicode__(self):
+        return self.title
+
+
+admin.site.register(RelatedItem, None)
+admin.site.register(AnotherRelatedItem, None)
diff --git a/tests/regressiontests/admin_related_lookup_popup/tests.py b/tests/regressiontests/admin_related_lookup_popup/tests.py
new file mode 100644
index 0000000..1cffd8e
--- /dev/null
+++ b/tests/regressiontests/admin_related_lookup_popup/tests.py
@@ -0,0 +1,99 @@
+"""
+This file demonstrates writing tests using the unittest module. These will pass
+when you run "manage.py test".
+
+Replace this with more appropriate tests for your application.
+"""
+
+from django.contrib.admin.views.main import IS_POPUP_VAR, POPUP_CALLBACK_VAR
+from django.contrib.auth.models import User
+from django.core.urlresolvers import reverse
+from django.test import TestCase
+from models import *
+
+
+class login(object):
+    def __init__(self, testcase, user, password):
+        self.testcase = testcase
+        success = testcase.client.login(username=user, password=password)
+        self.testcase.assertTrue(
+            success,
+            "login with username=%r, password=%r failed" % (user, password)
+        )
+
+    def __enter__(self):
+        pass
+
+    def __exit__(self, *args):
+        self.testcase.client.logout()
+
+
+class RelatedLookupPopupTest(TestCase):
+
+    def setUp(self):
+        User.objects.create_superuser('root', 'root@example.com', '123')
+        RelatedItem.objects.create(title='lorem')
+        RelatedItem.objects.create(title='ipsum')
+        RelatedItem.objects.create(title='dolorem')
+
+        AnotherRelatedItem.objects.create(title='lorem')
+        AnotherRelatedItem.objects.create(title='ipsum')
+        AnotherRelatedItem.objects.create(title='dolorem')
+        AnotherRelatedItem.objects.create(title='lorem')
+        AnotherRelatedItem.objects.create(title='ipsum')
+
+    def test_choose_from_changelist(self):
+        with login(self, 'root', '123'):
+            callbacks = {
+                'dismissRelatedItemLookupPopup': (reverse('admin:admin_related_lookup_popup_relateditem_changelist'), 3),
+                'dismissAnoterRelatedItemLookupPopup': (reverse('admin:admin_related_lookup_popup_anotherrelateditem_changelist'), 5),
+            }
+
+            for callback_name, opts in callbacks.items():
+                changelist_url, count = opts
+
+                response = self.client.get("%s?_callback=%s" % (changelist_url, callback_name))
+                self.assertContains(response, '<a href="1/">', 1, 200)
+                self.assertContains(response, '<a href="2/">', 1, 200)
+                self.assertContains(response, '<a href="3/">', 1, 200)
+                self.assertContains(response, 'onclick="opener.%s(' % callback_name, 0, 200)
+
+                response = self.client.get("%s?%s=1&_callback=%s" % \
+                                           (changelist_url, IS_POPUP_VAR, callback_name))
+                self.assertContains(response, '<a href="1/">', 0, 200)
+                self.assertContains(response, '<a href="2/">', 0, 200)
+                self.assertContains(response, '<a href="3/">', 0, 200)
+                self.assertContains(response, 'onclick="opener.%s(' % callback_name, count, 200)
+
+    def test_add_new_related(self):
+        with login(self, 'root', '123'):
+            callback_name = 'dismissRelatedItemLookupPopup'
+            add_url = reverse('admin:admin_related_lookup_popup_relateditem_add')
+
+            # check correct rendering form
+            response = self.client.get("%s?_popup=1&_callback=%s" % (add_url, callback_name))
+            self.assertEqual(response.status_code, 200)
+            self.assertContains(response, '<input type="hidden" name="_popup" value="1" />', 1, 200)
+            self.assertContains(response, '<input type="hidden" name="_callback" value="%s" />' % callback_name, 1, 200)
+
+            # check correct posting form
+            response = self.client.post(add_url, {
+                'title': 'zxc',
+                '_popup': 1,
+                '_callback': callback_name,
+            })
+            self.assertEqual(response.status_code, 200)
+            self.assertContains(response, '<script')
+            self.assertContains(response, callback_name)
+
+    def test_choose_new_from_changelist(self):
+        with login(self, 'root', '123'):
+            callback_name = 'dismissRelatedItemLookupPopup'
+            changelist_url = reverse('admin:admin_related_lookup_popup_relateditem_changelist')
+
+            response = self.client.get("%s?%s=1" % (changelist_url, IS_POPUP_VAR))
+            self.assertContains(response, 'add/?_popup=1', 1, 200)
+
+            response = self.client.get("%s?%s=1&%s=%s" % \
+                        (changelist_url, IS_POPUP_VAR, POPUP_CALLBACK_VAR, callback_name))
+            self.assertContains(response, 'add/?_popup=1&_callback=%s' % callback_name, 1, 200)
