Ticket #16260: 16260-admin-popup-callback.diff

File 16260-admin-popup-callback.diff, 12.0 KB (added by julien, 3 years ago)
  • django/contrib/admin/options.py

    diff --git a/django/contrib/admin/options.py b/django/contrib/admin/options.py
    index 4d23f8f..5e78bce 100644
    a b class ModelAdmin(BaseModelAdmin): 
    776776            self.message_user(request, msg + ' ' + _("You may edit it again below."))
    777777            if "_popup" in request.POST:
    778778                post_url_continue += "?_popup=1"
     779                if '_callback' in request.REQUEST:
     780                    post_url_continue += '&_callback=%s' % request.REQUEST.get('_callback')
    779781            return HttpResponseRedirect(post_url_continue % pk_value)
    780782
    781783        if "_popup" in request.POST:
     784            popup_callback = request.REQUEST.get('_callback', 'dismissAddAnotherPopup')
    782785            return HttpResponse(
    783786                '<!DOCTYPE html><html><head><title></title></head><body>'
    784                 '<script type="text/javascript">opener.dismissAddAnotherPopup(window, "%s", "%s");</script></body></html>' % \
     787                '<script type="text/javascript">opener.%s(window, "%s", "%s");</script></body></html>' % \
    785788                # escape() calls force_unicode.
    786                 (escape(pk_value), escapejs(obj)))
     789                (popup_callback, escape(pk_value), escapejs(obj)))
    787790        elif "_addanother" in request.POST:
    788791            self.message_user(request, msg + ' ' + (_("You may add another %s below.") % force_unicode(opts.verbose_name)))
    789792            return HttpResponseRedirect(request.path)
    class ModelAdmin(BaseModelAdmin): 
    10041007            'errors': helpers.AdminErrorList(form, formsets),
    10051008            'app_label': opts.app_label,
    10061009        }
     1010        if '_callback' in request.REQUEST:
     1011            context.update({'popup_callback': request.REQUEST.get('_callback')})
    10071012        context.update(extra_context or {})
    10081013        return self.render_change_form(request, context, form_url=form_url, add=True)
    10091014
    class ModelAdmin(BaseModelAdmin): 
    12341239            'selection_note_all': selection_note_all % {'total_count': cl.result_count},
    12351240            'title': cl.title,
    12361241            'is_popup': cl.is_popup,
     1242            'popup_callback': cl.popup_callback,
    12371243            'cl': cl,
    12381244            'media': media,
    12391245            'has_add_permission': self.has_add_permission(request),
  • django/contrib/admin/templates/admin/change_form.html

    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 b  
    3737{% endblock %}
    3838<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 %}
    3939<div>
    40 {% if is_popup %}<input type="hidden" name="_popup" value="1" />{% endif %}
     40{% if is_popup %}<input type="hidden" name="_popup" value="1" />{% if popup_callback %}<input type="hidden" name="_callback" value="{{ popup_callback }}" />{% endif %}{% endif %}
    4141{% if save_on_top %}{% block submit_buttons_top %}{% submit_row %}{% endblock %}{% endif %}
    4242{% if errors %}
    4343    <p class="errornote">
  • django/contrib/admin/templates/admin/change_list.html

    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 b  
    5454        <ul class="object-tools">
    5555          {% block object-tools-items %}
    5656            <li>
    57               <a href="{% url cl.opts|admin_urlname:'add' %}{% if is_popup %}?_popup=1{% endif %}" class="addlink">
     57              <a href="{% url cl.opts|admin_urlname:'add' %}{% if is_popup %}?_popup=1{% if popup_callback %}&_callback={{ popup_callback }}{% endif %}{% endif %}" class="addlink">
    5858                {% blocktrans with cl.opts.verbose_name as name %}Add {{ name }}{% endblocktrans %}
    5959              </a>
    6060            </li>
  • django/contrib/admin/templatetags/admin_list.py

    diff --git a/django/contrib/admin/templatetags/admin_list.py b/django/contrib/admin/templatetags/admin_list.py
    index 0f15781..92e4878 100644
    a b def items_for_result(cl, result, form): 
    228228                              table_tag,
    229229                              row_class,
    230230                              url,
    231                               format_html(' onclick="opener.dismissRelatedLookupPopup(window, {0}); return false;"', result_id)
    232                                 if cl.is_popup else '',
     231                              format_html(
     232                                  ' onclick="opener.{0}(window, {1}); return false;"',
     233                                  cl.get_popup_callback(), result_id
     234                              ) if cl.is_popup else '',
    233235                              result_repr,
    234236                              table_tag)
    235237        else:
  • django/contrib/admin/views/main.py

    diff --git a/django/contrib/admin/views/main.py b/django/contrib/admin/views/main.py
    index 85e03f3..ffd351b 100644
    a b SEARCH_VAR = 'q' 
    2424TO_FIELD_VAR = 't'
    2525IS_POPUP_VAR = 'pop'
    2626ERROR_FLAG = 'e'
     27POPUP_CALLBACK_VAR = '_callback'
     28POPUP_CALLBACK_DEFAULT = 'dismissRelatedLookupPopup'
    2729
    2830IGNORED_PARAMS = (
    29     ALL_VAR, ORDER_VAR, ORDER_TYPE_VAR, SEARCH_VAR, IS_POPUP_VAR, TO_FIELD_VAR)
     31    ALL_VAR, ORDER_VAR, ORDER_TYPE_VAR, SEARCH_VAR, IS_POPUP_VAR, TO_FIELD_VAR,
     32    POPUP_CALLBACK_VAR)
    3033
    3134# Text to display within change-list table cells if the value is blank.
    3235EMPTY_CHANGELIST_VALUE = ugettext_lazy('(None)')
    class ChangeList(object): 
    5760            self.page_num = 0
    5861        self.show_all = ALL_VAR in request.GET
    5962        self.is_popup = IS_POPUP_VAR in request.GET
     63        self.popup_callback = request.REQUEST.get(POPUP_CALLBACK_VAR)
    6064        self.to_field = request.GET.get(TO_FIELD_VAR)
    6165        self.params = dict(request.GET.items())
    6266        if PAGE_VAR in self.params:
    class ChangeList(object): 
    377381
    378382    def url_for_result(self, result):
    379383        return "%s/" % quote(getattr(result, self.pk_attname))
     384
     385    def get_popup_callback(self):
     386        if self.popup_callback is not None:
     387            return self.popup_callback
     388        return POPUP_CALLBACK_DEFAULT
     389 No newline at end of file
  • new file tests/regressiontests/admin_related_lookup_popup/models.py

    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
    - +  
     1from django.db import models
     2from django.contrib import admin
     3
     4
     5__all__ = ['RelatedItem', 'AnotherRelatedItem']
     6
     7
     8class RelatedItem(models.Model):
     9    title = models.CharField(max_length=25, blank=True, null=True)
     10
     11    def __unicode__(self):
     12        return self.title
     13
     14class AnotherRelatedItem(models.Model):
     15    title = models.CharField(max_length=15, blank=True, null=True)
     16
     17    def __unicode__(self):
     18        return self.title
     19
     20
     21admin.site.register(RelatedItem, None)
     22admin.site.register(AnotherRelatedItem, None)
  • new file tests/regressiontests/admin_related_lookup_popup/tests.py

    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
    - +  
     1"""
     2This file demonstrates writing tests using the unittest module. These will pass
     3when you run "manage.py test".
     4
     5Replace this with more appropriate tests for your application.
     6"""
     7
     8from django.contrib.admin.views.main import IS_POPUP_VAR, POPUP_CALLBACK_VAR
     9from django.contrib.auth.models import User
     10from django.core.urlresolvers import reverse
     11from django.test import TestCase
     12from models import *
     13
     14
     15class login(object):
     16    def __init__(self, testcase, user, password):
     17        self.testcase = testcase
     18        success = testcase.client.login(username=user, password=password)
     19        self.testcase.assertTrue(
     20            success,
     21            "login with username=%r, password=%r failed" % (user, password)
     22        )
     23
     24    def __enter__(self):
     25        pass
     26
     27    def __exit__(self, *args):
     28        self.testcase.client.logout()
     29
     30
     31class RelatedLookupPopupTest(TestCase):
     32
     33    def setUp(self):
     34        User.objects.create_superuser('root', 'root@example.com', '123')
     35        RelatedItem.objects.create(title='lorem')
     36        RelatedItem.objects.create(title='ipsum')
     37        RelatedItem.objects.create(title='dolorem')
     38
     39        AnotherRelatedItem.objects.create(title='lorem')
     40        AnotherRelatedItem.objects.create(title='ipsum')
     41        AnotherRelatedItem.objects.create(title='dolorem')
     42        AnotherRelatedItem.objects.create(title='lorem')
     43        AnotherRelatedItem.objects.create(title='ipsum')
     44
     45    def test_choose_from_changelist(self):
     46        with login(self, 'root', '123'):
     47            callbacks = {
     48                'dismissRelatedItemLookupPopup': (reverse('admin:admin_related_lookup_popup_relateditem_changelist'), 3),
     49                'dismissAnoterRelatedItemLookupPopup': (reverse('admin:admin_related_lookup_popup_anotherrelateditem_changelist'), 5),
     50            }
     51
     52            for callback_name, opts in callbacks.items():
     53                changelist_url, count = opts
     54
     55                response = self.client.get("%s?_callback=%s" % (changelist_url, callback_name))
     56                self.assertContains(response, '<a href="1/">', 1, 200)
     57                self.assertContains(response, '<a href="2/">', 1, 200)
     58                self.assertContains(response, '<a href="3/">', 1, 200)
     59                self.assertContains(response, 'onclick="opener.%s(' % callback_name, 0, 200)
     60
     61                response = self.client.get("%s?%s=1&_callback=%s" % \
     62                                           (changelist_url, IS_POPUP_VAR, callback_name))
     63                self.assertContains(response, '<a href="1/">', 0, 200)
     64                self.assertContains(response, '<a href="2/">', 0, 200)
     65                self.assertContains(response, '<a href="3/">', 0, 200)
     66                self.assertContains(response, 'onclick="opener.%s(' % callback_name, count, 200)
     67
     68    def test_add_new_related(self):
     69        with login(self, 'root', '123'):
     70            callback_name = 'dismissRelatedItemLookupPopup'
     71            add_url = reverse('admin:admin_related_lookup_popup_relateditem_add')
     72
     73            # check correct rendering form
     74            response = self.client.get("%s?_popup=1&_callback=%s" % (add_url, callback_name))
     75            self.assertEqual(response.status_code, 200)
     76            self.assertContains(response, '<input type="hidden" name="_popup" value="1" />', 1, 200)
     77            self.assertContains(response, '<input type="hidden" name="_callback" value="%s" />' % callback_name, 1, 200)
     78
     79            # check correct posting form
     80            response = self.client.post(add_url, {
     81                'title': 'zxc',
     82                '_popup': 1,
     83                '_callback': callback_name,
     84            })
     85            self.assertEqual(response.status_code, 200)
     86            self.assertContains(response, '<script')
     87            self.assertContains(response, callback_name)
     88
     89    def test_choose_new_from_changelist(self):
     90        with login(self, 'root', '123'):
     91            callback_name = 'dismissRelatedItemLookupPopup'
     92            changelist_url = reverse('admin:admin_related_lookup_popup_relateditem_changelist')
     93
     94            response = self.client.get("%s?%s=1" % (changelist_url, IS_POPUP_VAR))
     95            self.assertContains(response, 'add/?_popup=1', 1, 200)
     96
     97            response = self.client.get("%s?%s=1&%s=%s" % \
     98                        (changelist_url, IS_POPUP_VAR, POPUP_CALLBACK_VAR, callback_name))
     99            self.assertContains(response, 'add/?_popup=1&_callback=%s' % callback_name, 1, 200)
Back to Top