0

I want to query if an input value is in a form post and raise an error if it is not:

    try:
        next_page = request.POST.get('next_page')
    except AttributeError:
        raise ImproperlyConfigured(
            "No URL to redirect to.  Either provide a url or define"
            " a get_absolute_url method on the Model.")

However, if next_page is not provided this code results in next_page = None and the error is not raised. Where am I going wrong?

alias51
  • 8,178
  • 22
  • 94
  • 166
  • 1
    `try` is not always better than `if`, in fact in this case I'd argue that `if ... else ...` would be more readable. Your example fails because `get()` on a dictionary always returns something (`None` by default). You could have done `next_page = request.POST['next_page']` and caught `KeyError` exception. – dirkgroten Jan 07 '20 at 21:45
  • You mean just replace `AttributeError` with `KeyError`? – alias51 Jan 07 '20 at 21:55
  • No, `request.POST.get('next_page')` will never throw any error, but `request.POST['next_page']` will throw a `KeyError` if the key isn't present. – dirkgroten Jan 07 '20 at 21:56
  • And use bracket-deference rather than `get`, if you want to go that way. `get` doesn't throw anything on a missing key. – Peter DeGlopper Jan 07 '20 at 21:56
  • 1
    However, this doesn't account for the possibility that `next_page` is present but empty. That's why I would keep to a simple `if ... else ...`: `if next_page: redirect() else: raise ...`. This covers the case that `next_page` is `None` but also `''` – dirkgroten Jan 07 '20 at 21:57

2 Answers2

2

To check if a key is in the POST dictionary you can use a regular in

if 'next_page' not in request.POST:
    raise ImproperlyConfigured(
        "No URL to redirect to.  Either provide a url or define"
        " a get_absolute_url method on the Model.")
Iain Shelvington
  • 31,030
  • 3
  • 31
  • 50
1

Rather than use a try except block, you could just use a normal conditional clause to check if next_page is not None. (For clarity, I added a default value of None to the get method call if the 'next_page' key isn't found)

next_page = request.POST.get('next_page', None)

if next_page is not None:
   # redirect code
else:
    raise ImproperlyConfigured(
            "No URL to redirect to.  Either provide a url or define"
            " a get_absolute_url method on the Model.")

EDIT:

Another option based on asking forgiveness rather than permission:

try:
    redirect(request.POST.get('next_page'))
except KeyError:
    raise ImproperlyConfigured("text")

Here you don't need to check if the next_page value is None, you rely on the redirect function throwing an error if it receives None. You then catch that, and raise your Exception.

ekneiling
  • 159
  • 1
  • 8
  • Thanks, that's helpful. Why doesn't my example work though? What's failing? I understood it's always better to `try` than `if` isn't it? – alias51 Jan 07 '20 at 21:41
  • 1
    get() will return None if the key doesn’t exist by default, passing None as the second argument is redundant – Iain Shelvington Jan 07 '20 at 21:42
  • @IainShelvington Thanks. Should I be using `if` in this case? I understood it's always better / lower overhead to use `try` and `except`? – alias51 Jan 07 '20 at 21:42
  • @alias51`try except` and `if` statements aren't interchangeable where you should favor one over the other for performance. `try except` is primarily for error handling and `if` is for logical flow. Use whatever makes the most sense in the situation. In your case, you're determining `if` a value is `None` or not, so using an `if` statement is perfectly fine. Also, the `except` clause catches exceptions, not `None` values, which is why your example wasn't working as you expected. – ekneiling Jan 07 '20 at 22:04
  • 2
    https://stackoverflow.com/questions/12265451/ask-forgiveness-not-permission-explain has some discussion of the general philosophy of exceptions (forgiveness) vs. checking first (permission). – Peter DeGlopper Jan 07 '20 at 22:07
  • You need to use `request.POST['next_page']` to get a `KeyError` – Iain Shelvington Jan 07 '20 at 22:47