Raising Http Redirect

1,886 views
Skip to first unread message

Thomas Guettler

unread,
Jan 2, 2008, 4:49:59 AM1/2/08
to Django users
Hi,

The HTTP return codes 404 and 500 can be raised with an exception.

That's very handy. Unfortunately a Http Redirect can't be raised.
Do other django users thing this would be usefull, too?

I implemented it myself. But I think something like this should be in django.

#responseutils.py
class HttpRedirectException(Exception):
pass

# middleware.py
def process_exception(self, request, exception):
if isinstance(exception, responseutils.HttpRedirectException):
return django.http.HttpResponseRedirect(exception.args[0])

# usage
raise responseutils.HttpRedirectException(obj.get_absolute_url())

Thomas

James Bennett

unread,
Jan 2, 2008, 5:09:43 AM1/2/08
to django...@googlegroups.com
On Jan 2, 2008 3:49 AM, Thomas Guettler <h...@tbz-pariv.de> wrote:
> The HTTP return codes 404 and 500 can be raised with an exception.
>
> That's very handy. Unfortunately a Http Redirect can't be raised.
> Do other django users thing this would be usefull, too?

No. Exceptions represent "errors" in a program, and the 4xx and 5xx
status codes represent "errors" in HTTP, so that maps well. But 3xx
status codes in HTTP are not errors, so implementing them as
exceptions would feel awfully strange.


--
"Bureaucrat Conrad, you are technically correct -- the best kind of correct."

Forest Bond

unread,
Jan 2, 2008, 9:20:59 AM1/2/08
to django...@googlegroups.com
On Wed, Jan 02, 2008 at 04:09:43AM -0600, James Bennett wrote:
>
> On Jan 2, 2008 3:49 AM, Thomas Guettler <h...@tbz-pariv.de> wrote:
> > The HTTP return codes 404 and 500 can be raised with an exception.
> >
> > That's very handy. Unfortunately a Http Redirect can't be raised.
> > Do other django users thing this would be usefull, too?
>
> No. Exceptions represent "errors" in a program, and the 4xx and 5xx
> status codes represent "errors" in HTTP, so that maps well. But 3xx
> status codes in HTTP are not errors, so implementing them as
> exceptions would feel awfully strange.

I disagree. Exceptions represent "exceptional situations," not all of which are
necessarily errors. For instance, SystemExit is not really an error, is it?
What about StopIteration?

The "error condition" semantics of exceptions are injected.

More practically, in Python, exceptions provide a simple way to trigger a major
state change in the application from a lower level in the call stack. This is
frequently not an error.

A redirection exception seems natural to me; I've implemented something like
this myself in the past.

-Forest
--
Forest Bond
http://www.alittletooquiet.net

signature.asc

James Bennett

unread,
Jan 2, 2008, 10:35:33 AM1/2/08
to django...@googlegroups.com
On Jan 2, 2008 8:20 AM, Forest Bond <for...@alittletooquiet.net> wrote:
> I disagree. Exceptions represent "exceptional situations," not all of which are
> necessarily errors. For instance, SystemExit is not really an error, is it?
> What about StopIteration?

By that analogy as well, exceptions would be the wrong choice here:
what's "exceptional" about returning a redirect? A 404 or 500 is
exceptional -- it's something outside of otherwise-routine operation.
But redirecting from one page to another *is* a part of routine
operation.

So, again, I'm against this.

Thomas Guettler

unread,
Jan 2, 2008, 10:37:58 AM1/2/08
to django...@googlegroups.com
Am Mittwoch, 2. Januar 2008 11:09 schrieb James Bennett:
> On Jan 2, 2008 3:49 AM, Thomas Guettler <h...@tbz-pariv.de> wrote:
> > The HTTP return codes 404 and 500 can be raised with an exception.
> >
> > That's very handy. Unfortunately a Http Redirect can't be raised.
> > Do other django users thing this would be usefull, too?
>
> No. Exceptions represent "errors" in a program, and the 4xx and 5xx
> status codes represent "errors" in HTTP, so that maps well. But 3xx
> status codes in HTTP are not errors, so implementing them as
> exceptions would feel awfully strange.

Hi James,

in my case this redirect exception is a kind of error. But it is not
an error at http level.

My usecase:

The model MyModel has an attribute mtime. Everytime someone
edits it, the mtime gets updated.

The form to edit the Model has a hidden input with the mtime.

If someone tries to save a form, but someone else was faster,
then I want to leave the slower person a message, and redirect him to
the form again. His changes will be lost.

without exception:

response=obj.check_mtime(request)
if response:
return response

with exception:

obj.check_mtime(request)


Since the code will be written several times, I prefere the one line solution.

James Bennett

unread,
Jan 2, 2008, 11:00:10 AM1/2/08
to django...@googlegroups.com
On Jan 2, 2008 9:37 AM, Thomas Guettler <h...@tbz-pariv.de> wrote:
> If someone tries to save a form, but someone else was faster,
> then I want to leave the slower person a message, and redirect him to
> the form again. His changes will be lost.

Why not return a validation error from the form telling the user
what's happening, instead of silently throwing away their work? ;)

Forest Bond

unread,
Jan 2, 2008, 11:01:12 AM1/2/08
to django...@googlegroups.com
Hi,

On Wed, Jan 02, 2008 at 09:35:33AM -0600, James Bennett wrote:
> On Jan 2, 2008 8:20 AM, Forest Bond <for...@alittletooquiet.net> wrote:
> > I disagree. Exceptions represent "exceptional situations," not all of which are
> > necessarily errors. For instance, SystemExit is not really an error, is it?
> > What about StopIteration?
>
> By that analogy as well, exceptions would be the wrong choice here:
> what's "exceptional" about returning a redirect? A 404 or 500 is
> exceptional -- it's something outside of otherwise-routine operation.
> But redirecting from one page to another *is* a part of routine
> operation.

StopIteration represents a routine action: the end of a loop. What is
exceptional about it is the interruption in flow, much like a redirection can be
thought of as an interruption in content generation (in a view). An exception
means "stop what you're doing and deal with this new condition."

This is probably a pointless argument, though. Clearly, you prefer to use
exceptions exclusively for error conditions, and I don't mind (ab)using them for
other purposes as well. I view exceptions as a more general message-passing
mechanism with some advantageous properties, not just a red flag to throw when
things go sour. I wouldn't use them for everything, but they do lend themselves
to some "stop that and do this instead" situations.

signature.asc

Marty Alchin

unread,
Jan 2, 2008, 11:28:29 AM1/2/08
to django...@googlegroups.com
Given that I've thought a bit about this not too long ago[1], I'll
pipe in with my little bit of philosophy, along with some advice on
the topic at hand.

Exceptions are, by definition, exceptional. They defy the rule. That
could mean errors, but it could also mean any other situation that a
particular rule doesn't account for. Ultimately, you can only define
exceptions with regard to the rules they defy, and the rules followed
by a piece of code are dictated entirely by the developer of that
code. If you don't want your flow to accommodate a situation, you're
welcome to raise an exception and have other code handle that case.

However, in the case of Django, the framework itself can't possibly
accommodate everyone's idea of how rules should be written. Instead,
it has to take a middle-of-the-road approach, trying to cover the most
common situations, while allowing other situations to be handled
easily. Clearly having an exception for redirects won't be necessary
(or even good) for most Django users, so it's not something that will
make it into the framework itself. Especially since, as has already
been mentioned on this thread, it's quite possible to accomplish with
middleware.

If, however, you'd like to see the existing HTTP exceptions refactored
in such a way that you could subclass them to create a redirecting
exception without the middleware, that's an entirely separate issue,
and one that would probably be better received. It still might not
make it into trunk, but I would think that it would be a much better
suggestion than "I'm doing non-standard practice X, can it be added to
Django so I can save myself a dozen (or less!) lines of code?" I'd
recommend creating a ticket for generalizing HTTP exceptions so that
the exception class can dictate what response gets sent. But don't
expect me to implement it.

-Gul

[1] http://gulopine.gamemusic.org/2007/nov/21/except-the-unexpected/
(Sorry if the page loads slowly or not at all, the server's having
issues)

Reply all
Reply to author
Forward
0 new messages