1
0
mirror of https://github.com/django/django.git synced 2025-10-31 09:41:08 +00:00

Fixed #19505 -- A more flexible implementation for customizable admin redirect urls.

Work by Julien Phalip.

Refs #8001, #18310, #19505. See also 0b908b92a2.
This commit is contained in:
Julien Phalip
2012-12-22 20:00:08 +01:00
committed by Ramiro Morales
parent 4a71b84266
commit 35d1cd0b28
5 changed files with 144 additions and 174 deletions

View File

@@ -9,7 +9,7 @@ from django.forms.models import (modelform_factory, modelformset_factory,
inlineformset_factory, BaseInlineFormSet)
from django.contrib.contenttypes.models import ContentType
from django.contrib.admin import widgets, helpers
from django.contrib.admin.util import quote, unquote, flatten_fieldsets, get_deleted_objects, model_format_dict
from django.contrib.admin.util import unquote, flatten_fieldsets, get_deleted_objects, model_format_dict
from django.contrib.admin.templatetags.admin_static import static
from django.contrib import messages
from django.views.decorators.csrf import csrf_protect
@@ -38,6 +38,7 @@ HORIZONTAL, VERTICAL = 1, 2
# returns the <ul> class for a given radio_admin field
get_ul_class = lambda x: 'radiolist%s' % ((x == HORIZONTAL) and ' inline' or '')
class IncorrectLookupParameters(Exception):
pass
@@ -62,6 +63,7 @@ FORMFIELD_FOR_DBFIELD_DEFAULTS = {
csrf_protect_m = method_decorator(csrf_protect)
class BaseModelAdmin(six.with_metaclass(forms.MediaDefiningClass)):
"""Functionality common to both ModelAdmin and InlineAdmin."""
@@ -150,7 +152,7 @@ class BaseModelAdmin(six.with_metaclass(forms.MediaDefiningClass)):
})
if 'choices' not in kwargs:
kwargs['choices'] = db_field.get_choices(
include_blank = db_field.blank,
include_blank=db_field.blank,
blank_choice=[('', _('None'))]
)
return db_field.formfield(**kwargs)
@@ -787,49 +789,37 @@ class ModelAdmin(BaseModelAdmin):
"admin/change_form.html"
], context, current_app=self.admin_site.name)
def response_add(self, request, obj, post_url_continue='../%s/',
continue_editing_url=None, add_another_url=None,
hasperm_url=None, noperm_url=None):
def response_add(self, request, obj, post_url_continue=None):
"""
Determines the HttpResponse for the add_view stage.
:param request: HttpRequest instance.
:param obj: Object just added.
:param post_url_continue: Deprecated/undocumented.
:param continue_editing_url: URL where user will be redirected after
pressing 'Save and continue editing'.
:param add_another_url: URL where user will be redirected after
pressing 'Save and add another'.
:param hasperm_url: URL to redirect after a successful object creation
when the user has change permissions.
:param noperm_url: URL to redirect after a successful object creation
when the user has no change permissions.
"""
if post_url_continue != '../%s/':
warnings.warn("The undocumented 'post_url_continue' argument to "
"ModelAdmin.response_add() is deprecated, use the new "
"*_url arguments instead.", DeprecationWarning,
stacklevel=2)
opts = obj._meta
pk_value = obj.pk
app_label = opts.app_label
model_name = opts.module_name
site_name = self.admin_site.name
pk_value = obj._get_pk_val()
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:
msg = _('The %(name)s "%(obj)s" was added successfully. You may edit it again below.') % msg_dict
self.message_user(request, msg)
if continue_editing_url is None:
continue_editing_url = 'admin:%s_%s_change' % (app_label, model_name)
url = reverse(continue_editing_url, args=(quote(pk_value),),
current_app=site_name)
if post_url_continue is None:
post_url_continue = reverse('admin:%s_%s_change' %
(opts.app_label, opts.module_name),
args=(pk_value,),
current_app=self.admin_site.name)
else:
try:
post_url_continue = post_url_continue % pk_value
warnings.warn(
"The use of string formats for post_url_continue "
"in ModelAdmin.response_add() is deprecated. Provide "
"a pre-formatted url instead.",
DeprecationWarning, stacklevel=2)
except TypeError:
pass
if "_popup" in request.POST:
url += "?_popup=1"
return HttpResponseRedirect(url)
post_url_continue += "?_popup=1"
return HttpResponseRedirect(post_url_continue)
if "_popup" in request.POST:
return HttpResponse(
@@ -840,102 +830,61 @@ class ModelAdmin(BaseModelAdmin):
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)
if add_another_url is None:
add_another_url = 'admin:%s_%s_add' % (app_label, model_name)
url = reverse(add_another_url, current_app=site_name)
return HttpResponseRedirect(url)
return HttpResponseRedirect(request.path)
else:
msg = _('The %(name)s "%(obj)s" was added successfully.') % msg_dict
self.message_user(request, msg)
return self.response_post_save(request, obj)
# Figure out where to redirect. If the user has change permission,
# redirect to the change-list page for this object. Otherwise,
# redirect to the admin index.
if self.has_change_permission(request, None):
if hasperm_url is None:
hasperm_url = 'admin:%s_%s_changelist' % (app_label, model_name)
url = reverse(hasperm_url, current_app=site_name)
else:
if noperm_url is None:
noperm_url = 'admin:index'
url = reverse(noperm_url, current_app=site_name)
return HttpResponseRedirect(url)
def response_change(self, request, obj, continue_editing_url=None,
save_as_new_url=None, add_another_url=None,
hasperm_url=None, noperm_url=None):
def response_change(self, request, obj):
"""
Determines the HttpResponse for the change_view stage.
:param request: HttpRequest instance.
:param obj: Object just modified.
:param continue_editing_url: URL where user will be redirected after
pressing 'Save and continue editing'.
:param save_as_new_url: URL where user will be redirected after pressing
'Save as new' (when applicable).
:param add_another_url: URL where user will be redirected after pressing
'Save and add another'.
:param hasperm_url: URL to redirect after a successful object edition when
the user has change permissions.
:param noperm_url: URL to redirect after a successful object edition when
the user has no change permissions.
"""
opts = obj._meta
opts = self.model._meta
app_label = opts.app_label
model_name = opts.module_name
site_name = self.admin_site.name
verbose_name = opts.verbose_name
# Handle proxy models automatically created by .only() or .defer().
# Refs #14529
if obj._deferred:
opts_ = opts.proxy_for_model._meta
verbose_name = opts_.verbose_name
model_name = opts_.module_name
msg_dict = {'name': force_text(verbose_name), 'obj': force_text(obj)}
pk_value = obj._get_pk_val()
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)
if continue_editing_url is None:
continue_editing_url = 'admin:%s_%s_change' % (app_label, model_name)
url = reverse(continue_editing_url, args=(quote(obj.pk),),
current_app=site_name)
if "_popup" in request.POST:
url += "?_popup=1"
return HttpResponseRedirect(url)
if "_popup" in request.REQUEST:
return HttpResponseRedirect(request.path + "?_popup=1")
else:
return HttpResponseRedirect(request.path)
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)
if save_as_new_url is None:
save_as_new_url = 'admin:%s_%s_change' % (app_label, model_name)
url = reverse(save_as_new_url, args=(quote(obj.pk),),
current_app=site_name)
return HttpResponseRedirect(url)
return HttpResponseRedirect(reverse('admin:%s_%s_change' %
(opts.app_label, opts.module_name),
args=(pk_value,),
current_app=self.admin_site.name))
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)
if add_another_url is None:
add_another_url = 'admin:%s_%s_add' % (app_label, model_name)
url = reverse(add_another_url, current_app=site_name)
return HttpResponseRedirect(url)
return HttpResponseRedirect(reverse('admin:%s_%s_add' %
(opts.app_label, opts.module_name),
current_app=self.admin_site.name))
else:
msg = _('The %(name)s "%(obj)s" was changed successfully.') % msg_dict
self.message_user(request, msg)
# Figure out where to redirect. If the user has change permission,
# redirect to the change-list page for this object. Otherwise,
# redirect to the admin index.
if self.has_change_permission(request, None):
if hasperm_url is None:
hasperm_url = 'admin:%s_%s_changelist' % (app_label,
model_name)
url = reverse(hasperm_url, current_app=site_name)
else:
if noperm_url is None:
noperm_url = 'admin:index'
url = reverse(noperm_url, current_app=site_name)
return HttpResponseRedirect(url)
return self.response_post_save(request, obj)
def response_post_save(self, request, obj):
"""
Figure out where to redirect after the 'Save' button has been pressed.
If the user has change permission, redirect to the change-list page for
this object. Otherwise, redirect to the admin index.
"""
opts = self.model._meta
if self.has_change_permission(request, None):
post_url = reverse('admin:%s_%s_changelist' %
(opts.app_label, opts.module_name),
current_app=self.admin_site.name)
else:
post_url = reverse('admin:index',
current_app=self.admin_site.name)
return HttpResponseRedirect(post_url)
def response_action(self, request, queryset):
"""

View File

@@ -153,7 +153,7 @@ class UserAdmin(admin.ModelAdmin):
'admin/auth/user/change_password.html',
context, current_app=self.admin_site.name)
def response_add(self, request, obj, **kwargs):
def response_add(self, request, obj, post_url_continue=None):
"""
Determines the HttpResponse for the add_view stage. It mostly defers to
its superclass implementation but is customized because the User model
@@ -166,7 +166,8 @@ class UserAdmin(admin.ModelAdmin):
# * We are adding a user in a popup
if '_addanother' not in request.POST and '_popup' not in request.POST:
request.POST['_continue'] = 1
return super(UserAdmin, self).response_add(request, obj, **kwargs)
return super(UserAdmin, self).response_add(request, obj,
post_url_continue)
admin.site.register(Group, GroupAdmin)
admin.site.register(User, UserAdmin)