Make Django admin edit return to custom page?

21 views
Skip to first unread message

Ulf Kronman

unread,
Dec 29, 2007, 3:55:27 AM12/29/07
to Django users
Hi all,
I'm using Django to build a repository of scientific publications at
my university.

Now we need to edit publication records that have been supplied by our
departments and imported into the database.

I would like to be able to use the excellent Django admin interface
for this editing, but my problem is that I would like my editors to be
able to start from a custom-made list of publications that need
editing and then return back to this custom list, after having edited
a record in the admin interface.

The default behavior of the admin edit is to return the user to a
neutral listing of the type of records being edited. Is there a way to
change this behavior and make it return to another page, preferably
using some kind of dynamic referrer parameter?

Sorry if this is an admin FAQ, but I have not been able to locate any
info about it.

Regards,
Ulf

Malcolm Tredinnick

unread,
Jan 2, 2008, 4:57:53 PM1/2/08
to django...@googlegroups.com

On Sat, 2007-12-29 at 00:55 -0800, Ulf Kronman wrote:
> Hi all,
> I'm using Django to build a repository of scientific publications at
> my university.
>
> Now we need to edit publication records that have been supplied by our
> departments and imported into the database.
>
> I would like to be able to use the excellent Django admin interface
> for this editing, but my problem is that I would like my editors to be
> able to start from a custom-made list of publications that need
> editing and then return back to this custom list, after having edited
> a record in the admin interface.
>
> The default behavior of the admin edit is to return the user to a
> neutral listing of the type of records being edited. Is there a way to
> change this behavior and make it return to another page, preferably
> using some kind of dynamic referrer parameter?

The admin interface isn't really designed to be customised like that.
Rather, the principle is that if you can edit one record, you can edit
them all.

However, a bit of reading of the source -- in particular,
contrib.admin.views.main -- will reveal some approaches that could be
used if you really wanted to. For example, the change_stage view (which,
along with add_stage() is used to process a model submission) sends the
user back to "../" upon success. So you could write a custom URLConf
entry that overrides that URL (admin/<app_name>/<model>/) and presented
them with the page you want to show them.

That sort of thing requires a little bit of planning out, but I can say
from exprience that it generally works out fairly well. There's a little
bit of duplication, since you need to write a view that is almost, but
not quite, exactly like the standard admin view. However, you can use
the normal admin templates and everything.

It takes a little bit of tiem to get this to work, but it's not
impossible.

Regards,
Malcolm
\
--
Atheism is a non-prophet organization.
http://www.pointy-stick.com/blog/

Ulf Kronman

unread,
Jan 3, 2008, 10:01:00 AM1/3/08
to Django users
Hi Malcom,
and thanks for the reply.

> The admin interface isn't really designed to be customised like that.
> Rather, the principle is that if you can edit one record, you can edit
> them all.

OK, I guessed that I would get that answer, but I took a chance
anyhow.

> However, a bit of reading of the source -- in particular,
> contrib.admin.views.main -- will reveal some approaches that could be
> used if you really wanted to. For example, the change_stage view (which,
> along with add_stage() is used to process a model submission) sends the
> user back to "../" upon success. So you could write a custom URLConf
> entry that overrides that URL (admin/<app_name>/<model>/) and presented
> them with the page you want to show them.

That could be a solution to my problem. If I understand you right
here, I should write a URLConf that in my case intercepts the URL /
admin/publications/publication/ and points to a view that redirects
the user to the page he started from before editing the record in the
admin interface. I guess the address of the starting point has to be
stored as a session parameter, if I want it to be dynamic.

I also believe that I have to find a clever URL capturer for my custom
view, since I also want to be able to point back to the original /
admin/publications/publication/ list, if the user did not start from
the custom list, but actually came from the /admin/publications/
publication/, but I don't want it to loop, of course. It looks as if
the admin list view accepts the URL both with or without an ending
slash, but the edit form always returns to the list with an ending
slash, so maybe that little difference in the URLs could do the trick.

I'll get back with a report, if I get it working.

Thanks for your help,
Ulf

Ulf Kronman

unread,
Jan 4, 2008, 9:04:50 AM1/4/08
to Django users
Hi all,
I believe that I now have found a way to use the Django admin edit
form, addressed from an external page, and then get returned back to
the external page, rather than the default admin listing of records.

I got a first good hint from Malcolm, and after a little tweaking of
URL configs and a making custom "relay" view, I got it working. The
general idea is to intercept the URL pointing at the admin listing of
records and point to a custom view that directs the user back to the
external page.

But as I wanted the admin listing to be left untouched if you in fact
arrived to the admin edit from the admin listing of records, I had to
make a new URL pointing at it, to get there without disturbance of my
own previous interception.

This solution may not be rock-solid for the future, since it involves
a bit of tampering with the URL to the admin list, but I want to post
it here as a general idea, if someone else want to do something like
this. Maybe you can give me some feedback and suggestions for
improving the solution and/or making it more stable.

This is how the code looks:

The URLConf pointing at my relay view for external linking:
----------------------------------------------------------
from django.conf.urls.defaults import *
urlpatterns = patterns('kvalster.publications.views',
(r'^publication/(?P<publication_id>\d+)/admin_edit_relay',
'admin_edit_relay'),
)
-------------------------------------

The URLConf pointing at the relay for linking back:
--------------------------------------------------
from django.conf.urls.defaults import *
urlpatterns = patterns('',
(r'^admin/(publications)/(publication)/list$',
'django.contrib.admin.views.main.change_list'),
(r'^admin/publications/publication/$',
'kvalster.publications.views.admin_edit_relay'),
(r'^admin/', include('django.contrib.admin.urls')),
)
-------------------------------------

And the relay view itself:
#
======================================================================================
def admin_edit_relay(request, publication_id = ''):
''' Redirects to the admin edit page, and sets referrer as return
address
Redirects from the admin list, if user entered from a custom
publication list '''

# Check if user is coming from outside of admin area
if request.META['HTTP_REFERER'].find('admin') < 0 :

# Set an URL to return to, after editing, as a session
parameter
request.session['return_to'] = request.META['HTTP_REFERER']

# Send user to admin edit page
return HttpResponseRedirect('/admin/publications/publication/'
+ publication_id)

# If user is coming from admin edit
else:

# If we have a custom return to address set
if 'return_to' in request.session:

str_return_to = request.session['return_to']
del request.session['return_to']
return HttpResponseRedirect(str_return_to)

# Otherwise, return to ordinary admin list, with new custom
URL
else:

return HttpResponseRedirect('/admin/publications/
publication/list')

#
======================================================================================

This is how it works from an external page:

1. Links from the external publication list points to my relay view (/
publications/<id>/admin_edit_relay).
2. The relay view sets a session parameter return_to that has the
value of the referring URL and sends user on to admin edit page.
3. After editing and returning to the admin list of records my URLConf
intercepts and sends user to the relay once again, this time using the
session parameter to redirect the user to the initial page.

This is how it works from internal admin edit:

1. When you enter the URL /admin/publications/publication/ the relay
view intercepts, but as it sees that we are coming from the admin area
and don't have the session parameter return_to set, it redirects to
the URL /admin/publications/publication/list which works fine for
sending directly to the admin list view as long as parameters with
application and model name is sent with it in the URLConf:
(r'^admin/(publications)/(publication)/list$',
'django.contrib.admin.views.main.change_list')
2. The same applies when you are returning from the admin edit page;
the URL interception take an extra turn and makes the URL to /admin/
publications/publication/list , and thus stays at the admin listing.

Hope this can be of any use to anyone.

Regards,
Ulf

Malcolm Tredinnick

unread,
Jan 4, 2008, 7:24:05 PM1/4/08
to django...@googlegroups.com

On Fri, 2008-01-04 at 06:04 -0800, Ulf Kronman wrote:
[...]

> This solution may not be rock-solid for the future, since it involves
> a bit of tampering with the URL to the admin list,

Barring any completely hidden and totally showstopping bug, you can
count on admin URLs being stable. "Cool URIs don't change" and all that.
Because somebody may have bookmarked a link to such a URL, if we were to
change it, we would be hurting users (not just application developers,
but their users -- the people sitting in front of browsers we have no
way of contacting).

So you can be fairly comfortable with relying on a stable URL structure.

Regards,
Malcolm

--
I've got a mind like a... a... what's that thing called?
http://www.pointy-stick.com/blog/

Reply all
Reply to author
Forward
0 new messages