Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Fixed #6903 - Preserve admin changelist filters after saving or delet…

…ing an object
  • Loading branch information...
commit c86a9b63984f6692d478f6f70e3c78de4ec41814 1 parent 2c4fe76
@loic loic authored
View
107 django/contrib/admin/options.py
@@ -13,6 +13,7 @@
model_format_dict, NestedObjects, lookup_needs_distinct)
from django.contrib.admin import validation
from django.contrib.admin.templatetags.admin_static import static
+from django.contrib.admin.templatetags.admin_urls import add_preserved_filters
from django.contrib import messages
from django.views.decorators.csrf import csrf_protect
from django.core.exceptions import PermissionDenied, ValidationError, FieldError
@@ -33,6 +34,7 @@
from django.utils.safestring import mark_safe
from django.utils import six
from django.utils.deprecation import RenameMethodsBase
+from django.utils.http import urlencode
from django.utils.text import capfirst, get_text_list
from django.utils.translation import ugettext as _
from django.utils.translation import ungettext
@@ -393,6 +395,7 @@ class ModelAdmin(BaseModelAdmin):
save_as = False
save_on_top = False
paginator = Paginator
+ preserve_filters = True
inlines = []
# Custom templates (designed to be over-ridden in subclasses)
@@ -755,6 +758,27 @@ def get_list_filter(self, request):
"""
return self.list_filter
+ def get_preserved_filters(self, request):
+ """
+ Returns the preserved filters querystring.
+ """
+
+ # FIXME: We can remove that getattr as soon as #20619 is fixed.
+ match = getattr(request, 'resolver_match', None)
+
+ if self.preserve_filters and match:
+ opts = self.model._meta
+ current_url = '%s:%s' % (match.namespace, match.url_name)
+ changelist_url = 'admin:%s_%s_changelist' % (opts.app_label, opts.model_name)
+ if current_url == changelist_url:
+ preserved_filters = request.GET.urlencode()
+ else:
+ preserved_filters = request.GET.get('_changelist_filters')
+
+ if preserved_filters:
+ return urlencode({'_changelist_filters': preserved_filters})
+ return ''
+
def construct_change_message(self, request, form, formsets):
"""
Construct a change message from a changed object.
@@ -846,6 +870,8 @@ def save_related(self, request, form, formsets, change):
def render_change_form(self, request, context, add=False, change=False, form_url='', obj=None):
opts = self.model._meta
app_label = opts.app_label
+ preserved_filters = self.get_preserved_filters(request)
+ form_url = add_preserved_filters({'preserved_filters': preserved_filters, 'opts': opts}, form_url)
context.update({
'add': add,
'change': change,
@@ -877,11 +903,19 @@ def response_add(self, request, obj, post_url_continue=None):
"""
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 "_continue" in request.POST:
+ if "_popup" in request.POST:
+ return HttpResponse(
+ '<!DOCTYPE html><html><head><title></title></head><body>'
+ '<script type="text/javascript">opener.dismissAddAnotherPopup(window, "%s", "%s");</script></body></html>' % \
+ # escape() calls force_text.
+ (escape(pk_value), escapejs(obj)))
+
+ elif "_continue" in request.POST:
msg = _('The %(name)s "%(obj)s" was added successfully. You may edit it again below.') % msg_dict
self.message_user(request, msg, messages.SUCCESS)
if post_url_continue is None:
@@ -889,20 +923,16 @@ def response_add(self, request, obj, post_url_continue=None):
(opts.app_label, opts.model_name),
args=(pk_value,),
current_app=self.admin_site.name)
- if "_popup" in request.POST:
- post_url_continue += "?_popup=1"
+ post_url_continue = add_preserved_filters({'preserved_filters': preserved_filters, 'opts': opts}, post_url_continue)
return HttpResponseRedirect(post_url_continue)
- if "_popup" in request.POST:
- return HttpResponse(
- '<!DOCTYPE html><html><head><title></title></head><body>'
- '<script type="text/javascript">opener.dismissAddAnotherPopup(window, "%s", "%s");</script></body></html>' % \
- # escape() calls force_text.
- (escape(pk_value), escapejs(obj)))
elif "_addanother" in request.POST:
msg = _('The %(name)s "%(obj)s" was added successfully. You may add another %(name)s below.') % msg_dict
self.message_user(request, msg, messages.SUCCESS)
- return HttpResponseRedirect(request.path)
+ redirect_url = request.path
+ redirect_url = add_preserved_filters({'preserved_filters': preserved_filters, 'opts': opts}, redirect_url)
+ return HttpResponseRedirect(redirect_url)
+
else:
msg = _('The %(name)s "%(obj)s" was added successfully.') % msg_dict
self.message_user(request, msg, messages.SUCCESS)
@@ -913,30 +943,36 @@ def response_change(self, request, obj):
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)
msg_dict = {'name': force_text(opts.verbose_name), 'obj': force_text(obj)}
if "_continue" in request.POST:
msg = _('The %(name)s "%(obj)s" was changed successfully. You may edit it again below.') % msg_dict
self.message_user(request, msg, messages.SUCCESS)
- if "_popup" in request.REQUEST:
- return HttpResponseRedirect(request.path + "?_popup=1")
- else:
- return HttpResponseRedirect(request.path)
+ redirect_url = request.path
+ redirect_url = add_preserved_filters({'preserved_filters': preserved_filters, 'opts': opts}, redirect_url)
+ return HttpResponseRedirect(redirect_url)
+
elif "_saveasnew" in request.POST:
msg = _('The %(name)s "%(obj)s" was added successfully. You may edit it again below.') % msg_dict
self.message_user(request, msg, messages.SUCCESS)
- return HttpResponseRedirect(reverse('admin:%s_%s_change' %
- (opts.app_label, opts.model_name),
- args=(pk_value,),
- current_app=self.admin_site.name))
+ redirect_url = reverse('admin:%s_%s_change' %
+ (opts.app_label, opts.model_name),
+ args=(pk_value,),
+ current_app=self.admin_site.name)
+ redirect_url = add_preserved_filters({'preserved_filters': preserved_filters, 'opts': opts}, redirect_url)
+ return HttpResponseRedirect(redirect_url)
+
elif "_addanother" in request.POST:
msg = _('The %(name)s "%(obj)s" was changed successfully. You may add another %(name)s below.') % msg_dict
self.message_user(request, msg, messages.SUCCESS)
- return HttpResponseRedirect(reverse('admin:%s_%s_add' %
- (opts.app_label, opts.model_name),
- current_app=self.admin_site.name))
+ redirect_url = reverse('admin:%s_%s_add' %
+ (opts.app_label, opts.model_name),
+ current_app=self.admin_site.name)
+ redirect_url = add_preserved_filters({'preserved_filters': preserved_filters, 'opts': opts}, redirect_url)
+ return HttpResponseRedirect(redirect_url)
+
else:
msg = _('The %(name)s "%(obj)s" was changed successfully.') % msg_dict
self.message_user(request, msg, messages.SUCCESS)
@@ -952,6 +988,8 @@ def response_post_save_add(self, request, obj):
post_url = reverse('admin:%s_%s_changelist' %
(opts.app_label, opts.model_name),
current_app=self.admin_site.name)
+ preserved_filters = self.get_preserved_filters(request)
+ post_url = add_preserved_filters({'preserved_filters': preserved_filters, 'opts': opts}, post_url)
else:
post_url = reverse('admin:index',
current_app=self.admin_site.name)
@@ -963,10 +1001,13 @@ def response_post_save_change(self, request, obj):
when editing an existing object.
"""
opts = self.model._meta
+
if self.has_change_permission(request, None):
post_url = reverse('admin:%s_%s_changelist' %
(opts.app_label, opts.model_name),
current_app=self.admin_site.name)
+ preserved_filters = self.get_preserved_filters(request)
+ post_url = add_preserved_filters({'preserved_filters': preserved_filters, 'opts': opts}, post_url)
else:
post_url = reverse('admin:index',
current_app=self.admin_site.name)
@@ -1122,6 +1163,7 @@ def add_view(self, request, form_url='', extra_context=None):
'inline_admin_formsets': inline_admin_formsets,
'errors': helpers.AdminErrorList(form, formsets),
'app_label': opts.app_label,
+ 'preserved_filters': self.get_preserved_filters(request),
}
context.update(extra_context or {})
return self.render_change_form(request, context, form_url=form_url, add=True)
@@ -1214,6 +1256,7 @@ def change_view(self, request, object_id, form_url='', extra_context=None):
'inline_admin_formsets': inline_admin_formsets,
'errors': helpers.AdminErrorList(form, formsets),
'app_label': opts.app_label,
+ 'preserved_filters': self.get_preserved_filters(request),
}
context.update(extra_context or {})
return self.render_change_form(request, context, change=True, obj=obj, form_url=form_url)
@@ -1357,11 +1400,13 @@ def changelist_view(self, request, extra_context=None):
'cl': cl,
'media': media,
'has_add_permission': self.has_add_permission(request),
+ 'opts': cl.opts,
'app_label': app_label,
'action_form': action_form,
'actions_on_top': self.actions_on_top,
'actions_on_bottom': self.actions_on_bottom,
'actions_selection_counter': self.actions_selection_counter,
+ 'preserved_filters': self.get_preserved_filters(request),
}
context.update(extra_context or {})
@@ -1406,12 +1451,16 @@ def delete_view(self, request, object_id, extra_context=None):
'obj': force_text(obj_display)},
messages.SUCCESS)
- if not self.has_change_permission(request, None):
- return HttpResponseRedirect(reverse('admin:index',
- current_app=self.admin_site.name))
- return HttpResponseRedirect(reverse('admin:%s_%s_changelist' %
- (opts.app_label, opts.model_name),
- current_app=self.admin_site.name))
+ if self.has_change_permission(request, None):
+ post_url = reverse('admin:%s_%s_changelist' %
+ (opts.app_label, opts.model_name),
+ current_app=self.admin_site.name)
+ preserved_filters = self.get_preserved_filters(request)
+ post_url = add_preserved_filters({'preserved_filters': preserved_filters, 'opts': opts}, post_url)
+ else:
+ post_url = reverse('admin:index',
+ current_app=self.admin_site.name)
+ return HttpResponseRedirect(post_url)
object_name = force_text(opts.verbose_name)
@@ -1429,6 +1478,7 @@ def delete_view(self, request, object_id, extra_context=None):
"protected": protected,
"opts": opts,
"app_label": app_label,
+ 'preserved_filters': self.get_preserved_filters(request),
}
context.update(extra_context or {})
@@ -1463,6 +1513,7 @@ def history_view(self, request, object_id, extra_context=None):
'object': obj,
'app_label': app_label,
'opts': opts,
+ 'preserved_filters': self.get_preserved_filters(request),
}
context.update(extra_context or {})
return TemplateResponse(request, self.object_history_template or [
View
8 django/contrib/admin/templates/admin/change_form.html
@@ -1,6 +1,5 @@
{% extends "admin/base_site.html" %}
-{% load i18n admin_static admin_modify %}
-{% load admin_urls %}
+{% load i18n admin_urls admin_static admin_modify %}
{% block extrahead %}{{ block.super }}
<script type="text/javascript" src="{% url 'admin:jsi18n' %}"></script>
@@ -29,7 +28,10 @@
{% if change %}{% if not is_popup %}
<ul class="object-tools">
{% block object-tools-items %}
- <li><a href="{% url opts|admin_urlname:'history' original.pk|admin_urlquote %}" class="historylink">{% trans "History" %}</a></li>
+ <li>
+ {% url opts|admin_urlname:'history' original.pk|admin_urlquote as history_url %}
+ <a href="{% add_preserved_filters history_url %}" class="historylink">{% trans "History" %}</a>
+ </li>
{% if has_absolute_url %}<li><a href="{% url 'admin:view_on_site' content_type_id original.pk %}" class="viewsitelink">{% trans "View on site" %}</a></li>{% endif%}
{% endblock %}
</ul>
View
6 django/contrib/admin/templates/admin/change_list.html
@@ -1,6 +1,5 @@
{% extends "admin/base_site.html" %}
-{% load i18n admin_static admin_list %}
-{% load admin_urls %}
+{% load i18n admin_urls admin_static admin_list %}
{% block extrastyle %}
{{ block.super }}
@@ -54,7 +53,8 @@
<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">
+ {% url cl.opts|admin_urlname:'add' as add_url %}
+ <a href="{% add_preserved_filters add_url is_popup %}" class="addlink">
{% blocktrans with cl.opts.verbose_name as name %}Add {{ name }}{% endblocktrans %}
</a>
</li>
View
3  django/contrib/admin/templates/admin/delete_confirmation.html
@@ -1,6 +1,5 @@
{% extends "admin/base_site.html" %}
-{% load i18n %}
-{% load admin_urls %}
+{% load i18n admin_urls %}
{% block breadcrumbs %}
<div class="breadcrumbs">
View
3  django/contrib/admin/templates/admin/delete_selected_confirmation.html
@@ -1,6 +1,5 @@
{% extends "admin/base_site.html" %}
-{% load i18n l10n %}
-{% load admin_urls %}
+{% load i18n l10n admin_urls %}
{% block breadcrumbs %}
<div class="breadcrumbs">
View
3  django/contrib/admin/templates/admin/object_history.html
@@ -1,6 +1,5 @@
{% extends "admin/base_site.html" %}
-{% load i18n %}
-{% load admin_urls %}
+{% load i18n admin_urls %}
{% block breadcrumbs %}
<div class="breadcrumbs">
View
5 django/contrib/admin/templates/admin/submit_line.html
@@ -1,7 +1,10 @@
{% load i18n admin_urls %}
<div class="submit-row">
{% if show_save %}<input type="submit" value="{% trans 'Save' %}" class="default" name="_save" />{% endif %}
-{% if show_delete_link %}<p class="deletelink-box"><a href="{% url opts|admin_urlname:'delete' original.pk|admin_urlquote %}" class="deletelink">{% trans "Delete" %}</a></p>{% endif %}
+{% if show_delete_link %}
+ {% url opts|admin_urlname:'delete' original.pk|admin_urlquote as delete_url %}
+ <p class="deletelink-box"><a href="{% add_preserved_filters delete_url %}" class="deletelink">{% trans "Delete" %}</a></p>
+{% endif %}
{% if show_save_as_new %}<input type="submit" value="{% trans 'Save as new' %}" name="_saveasnew" />{%endif%}
{% if show_save_and_add_another %}<input type="submit" value="{% trans 'Save and add another' %}" name="_addanother" />{% endif %}
{% if show_save_and_continue %}<input type="submit" value="{% trans 'Save and continue editing' %}" name="_continue" />{% endif %}
View
2  django/contrib/admin/templatetags/admin_list.py
@@ -2,6 +2,7 @@
import datetime
+from django.contrib.admin.templatetags.admin_urls import add_preserved_filters
from django.contrib.admin.util import (lookup_field, display_for_field,
display_for_value, label_for_field)
from django.contrib.admin.views.main import (ALL_VAR, EMPTY_CHANGELIST_VALUE,
@@ -217,6 +218,7 @@ def items_for_result(cl, result, form):
table_tag = {True:'th', False:'td'}[first]
first = False
url = cl.url_for_result(result)
+ url = add_preserved_filters({'preserved_filters': cl.preserved_filters, 'opts': cl.opts}, url)
# Convert the pk to something that can be used in Javascript.
# Problem cases are long ints (23L) and non-ASCII strings.
if cl.to_field:
View
3  django/contrib/admin/templatetags/admin_modify.py
@@ -37,7 +37,8 @@ def submit_row(context):
not is_popup and (not save_as or context['add']),
'show_save_and_continue': not is_popup and context['has_change_permission'],
'is_popup': is_popup,
- 'show_save': True
+ 'show_save': True,
+ 'preserved_filters': context.get('preserved_filters'),
}
if context.get('original') is not None:
ctx['original'] = context['original']
View
42 django/contrib/admin/templatetags/admin_urls.py
@@ -1,8 +1,17 @@
+from django.utils.http import urlencode
+
+try:
+ from urllib.parse import parse_qsl, urlparse, urlunparse
+except ImportError:
+ from urlparse import parse_qsl, urlparse, urlunparse
+
from django import template
from django.contrib.admin.util import quote
+from django.core.urlresolvers import resolve, Resolver404
register = template.Library()
+
@register.filter
def admin_urlname(value, arg):
return 'admin:%s_%s_%s' % (value.app_label, value.model_name, arg)
@@ -11,3 +20,36 @@ def admin_urlname(value, arg):
@register.filter
def admin_urlquote(value):
return quote(value)
+
+
+@register.simple_tag(takes_context=True)
+def add_preserved_filters(context, url, popup=False):
+ opts = context.get('opts')
+ preserved_filters = context.get('preserved_filters')
+
+ parsed_url = list(urlparse(url))
+ parsed_qs = dict(parse_qsl(parsed_url[4]))
+ merged_qs = dict()
+
+ if opts and preserved_filters:
+ preserved_filters = dict(parse_qsl(preserved_filters))
+
+ try:
+ match = resolve(url)
+ except Resolver404:
+ pass
+ else:
+ current_url = '%s:%s' % (match.namespace, match.url_name)
+ changelist_url = 'admin:%s_%s_changelist' % (opts.app_label, opts.model_name)
+ if changelist_url == current_url and '_changelist_filters' in preserved_filters:
+ preserved_filters = dict(parse_qsl(preserved_filters['_changelist_filters']))
+
+ merged_qs.update(preserved_filters)
+
+ if popup:
+ merged_qs['_popup'] = 1
+
+ merged_qs.update(parsed_qs)
+
+ parsed_url[4] = urlencode(merged_qs)
+ return urlunparse(parsed_url)
View
1  django/contrib/admin/views/main.py
@@ -59,6 +59,7 @@ def __init__(self, request, model, list_display, list_display_links,
self.list_per_page = list_per_page
self.list_max_show_all = list_max_show_all
self.model_admin = model_admin
+ self.preserved_filters = model_admin.get_preserved_filters(request)
# Get search parameters from the query string.
try:
View
8 docs/ref/contrib/admin/index.txt
@@ -870,6 +870,14 @@ subclass::
``prepopulated_fields`` doesn't accept ``DateTimeField``, ``ForeignKey``,
nor ``ManyToManyField`` fields.
+.. attribute:: ModelAdmin.preserve_filters
+
+ .. versionadded:: 1.6
+
+ The admin now preserves filters on the list view after creating, editing
+ or deleting an object. You can restore the previous behavior of clearing
+ filters by setting this attribute to ``False``.
+
.. attribute:: ModelAdmin.radio_fields
By default, Django's admin uses a select-box interface (<select>) for
View
15 docs/releases/1.6.txt
@@ -325,6 +325,11 @@ Minor features
:ref:`see the updated recommendation <raising-validation-error>` for raising
a ``ValidationError``.
+* :class:`~django.contrib.admin.ModelAdmin` now preserves filters on the list view
+ after creating, editing or deleting an object. It's possible to restore the previous
+ behavior of clearing filters by setting the
+ :attr:`~django.contrib.admin.ModelAdmin.preserve_filters` attribute to ``False``.
+
Backwards incompatible changes in 1.6
=====================================
@@ -634,6 +639,16 @@ will render something like:
If you want to keep the current behavior of rendering ``label_tag`` without
the ``label_suffix``, instantiate the form ``label_suffix=''``.
+Admin views ``_changelist_filters`` GET parameter
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+To achieve preserving and restoring list view filters, admin views now
+pass around the `_changelist_filters` GET parameter. It's important that you
+account for that change if you have custom admin templates or if your tests
+rely on the previous URLs. If you want to revert to the original behavior you
+can set the
+:attr:`~django.contrib.admin.ModelAdmin.preserve_filters` attribute to ``False``.
+
Miscellaneous
~~~~~~~~~~~~~
View
153 tests/admin_views/tests.py
@@ -4157,3 +4157,156 @@ def test_message_extra_tags(self):
self.assertContains(response,
'<li class="extra_tag info">Test tags</li>',
html=True)
+
+
+@override_settings(PASSWORD_HASHERS=('django.contrib.auth.hashers.SHA1PasswordHasher',))
+class AdminKeepChangeListFiltersTests(TestCase):
+ urls = "admin_views.urls"
+ fixtures = ['admin-views-users.xml']
+
+ def setUp(self):
+ self.client.login(username='super', password='secret')
+
+ def tearDown(self):
+ self.client.logout()
+
+ def get_changelist_filters_querystring(self):
+ return urlencode({
+ 'is_superuser__exact': 0,
+ 'is_staff__exact': 0,
+ })
+
+ def get_preserved_filters_querystring(self):
+ return urlencode({
+ '_changelist_filters': self.get_changelist_filters_querystring()
+ })
+
+ def get_sample_user_id(self):
+ return 104
+
+ def get_changelist_url(self):
+ return '%s?%s' % (
+ reverse('admin:auth_user_changelist'),
+ self.get_changelist_filters_querystring(),
+ )
+
+ def get_add_url(self):
+ return '%s?%s' % (
+ reverse('admin:auth_user_add'),
+ self.get_preserved_filters_querystring(),
+ )
+
+ def get_change_url(self, user_id=None):
+ if user_id is None:
+ user_id = self.get_sample_user_id()
+ return "%s?%s" % (
+ reverse('admin:auth_user_change', args=(user_id,)),
+ self.get_preserved_filters_querystring(),
+ )
+
+ def get_history_url(self, user_id=None):
+ if user_id is None:
+ user_id = self.get_sample_user_id()
+ return "%s?%s" % (
+ reverse('admin:auth_user_history', args=(user_id,)),
+ self.get_preserved_filters_querystring(),
+ )
+
+ def get_delete_url(self, user_id=None):
+ if user_id is None:
+ user_id = self.get_sample_user_id()
+ return "%s?%s" % (
+ reverse('admin:auth_user_delete', args=(user_id,)),
+ self.get_preserved_filters_querystring(),
+ )
+
+ def test_changelist_view(self):
+ response = self.client.get(self.get_changelist_url())
+ self.assertEqual(response.status_code, 200)
+
+ # Check the `change_view` link has the correct querystring.
+ detail_link = """<a href="%s">joepublic</a>""" % self.get_change_url()
+ self.assertContains(response, detail_link, count=1)
+
+ def test_change_view(self):
+ # Get the `change_view`.
+ response = self.client.get(self.get_change_url())
+ self.assertEqual(response.status_code, 200)
+
+ # Check the form action.
+ form_action = """<form enctype="multipart/form-data" action="?%s" method="post" id="user_form">""" % self.get_preserved_filters_querystring()
+ self.assertContains(response, form_action, count=1)
+
+ # Check the history link.
+ history_link = """<a href="%s" class="historylink">History</a>""" % self.get_history_url()
+ self.assertContains(response, history_link, count=1)
+
+ # Check the delete link.
+ delete_link = """<a href="%s" class="deletelink">Delete</a>""" % (self.get_delete_url())
+ self.assertContains(response, delete_link, count=1)
+
+ # Test redirect on "Save".
+ post_data = {
+ 'username': 'joepublic',
+ 'last_login_0': '2007-05-30',
+ 'last_login_1': '13:20:10',
+ 'date_joined_0': '2007-05-30',
+ 'date_joined_1': '13:20:10',
+ }
+
+ post_data['_save'] = 1
+ response = self.client.post(self.get_change_url(), data=post_data)
+ self.assertRedirects(response, self.get_changelist_url())
+ post_data.pop('_save')
+
+ # Test redirect on "Save and continue".
+ post_data['_continue'] = 1
+ response = self.client.post(self.get_change_url(), data=post_data)
+ self.assertRedirects(response, self.get_change_url())
+ post_data.pop('_continue')
+
+ # Test redirect on "Save and add new".
+ post_data['_addanother'] = 1
+ response = self.client.post(self.get_change_url(), data=post_data)
+ self.assertRedirects(response, self.get_add_url())
+ post_data.pop('_addanother')
+
+ def test_add_view(self):
+ # Get the `add_view`.
+ response = self.client.get(self.get_add_url())
+ self.assertEqual(response.status_code, 200)
+
+ # Check the form action.
+ form_action = """<form enctype="multipart/form-data" action="?%s" method="post" id="user_form">""" % self.get_preserved_filters_querystring()
+ self.assertContains(response, form_action, count=1)
+
+ # Test redirect on "Save".
+ post_data = {
+ 'username': 'dummy',
+ 'password1': 'test',
+ 'password2': 'test',
+ }
+
+ post_data['_save'] = 1
+ response = self.client.post(self.get_add_url(), data=post_data)
+ self.assertRedirects(response, self.get_change_url(self.get_sample_user_id() + 1))
+ post_data.pop('_save')
+
+ # Test redirect on "Save and continue".
+ post_data['username'] = 'dummy2'
+ post_data['_continue'] = 1
+ response = self.client.post(self.get_add_url(), data=post_data)
+ self.assertRedirects(response, self.get_change_url(self.get_sample_user_id() + 2))
+ post_data.pop('_continue')
+
+ # Test redirect on "Save and add new".
+ post_data['username'] = 'dummy3'
+ post_data['_addanother'] = 1
+ response = self.client.post(self.get_add_url(), data=post_data)
+ self.assertRedirects(response, self.get_add_url())
+ post_data.pop('_addanother')
+
+ def test_delete_view(self):
+ # Test redirect on "Delete".
+ response = self.client.post(self.get_delete_url(), {'post': 'yes'})
+ self.assertRedirects(response, self.get_changelist_url())
Please sign in to comment.
Something went wrong with that request. Please try again.