2

Coming from Flask, request.args[key] and request.form[key] responds with 400 if the key doesn't exist. This has a nice property of failing fast.

In Django, request.GET[key] and request.FORM[key] raises HttpResponseBadRequest if the key doesn't exist, which causes your API to respond with a 500 status if unhandled. I've seen other answers recommending request.GET.get(key), but that inadvertently loosens the API contract that could allow client-side bugs to slip by (e.g. a query parameter typo, forgetting to include a param, etc).

I could manually check for required query params:

arg1 = request.POST.get('arg1')
if not arg1:
    raise HttpBadRequest('"arg1" was not provided.')

arg2 = request.POST.get('arg2')
if not arg2:
    raise HttpBadRequest('"arg1" was not provided.')

arg3 = request.POST.get('arg3')
if not arg3:
    raise HttpBadRequest('"arg3" was not provided.')

But that leaves a lot of room for error. (Did you notice the typo?)

I could manually handle HttpResponseBadRequest:

def my_view(request):
    try:
        arg1 = request.POST['arg1']
        arg2 = request.POST['arg2']
        arg3 = request.POST['arg3']
    except MultiValueDictKeyError as ex:
        raise HttpBadRequest('"{}" was not provided.'.format(ex))

But now you have an extra thing to remember when writing views.

Compare the above examples to Flask's equivalent:

arg1 = request.form['arg1']
arg2 = request.form['arg2']
arg3 = request.form['arg3']

How can I write the same thing in Django without extra boilerplate in my views and have it respond with 400 when a param is missing?

Community
  • 1
  • 1
Joe
  • 16,328
  • 12
  • 61
  • 75

1 Answers1

5

This is exactly you should use Django forms. They are the validation framework that checks the user input and returns errors when it is not valid.

(Note, it's not the accessing of the nonexistent key that raises BadRequest; it raises MultiValueDictKeyError, as one of your snippet notes, and if that is unhandled the response middleware will return BadRequest.)

Daniel Roseman
  • 588,541
  • 66
  • 880
  • 895
  • Thanks! This seems overkill for simple JSON-based API views though. Are Django forms still used for that? – Joe Feb 06 '16 at 02:22