I'm Matthew J. Morrison.

A Passionate, professional software developer & hobbyist; Language nerd & regular user of Unix, Python, Ruby & JavaScript.

Fork me on GitHub

My pair and I ran into an issue today that got us hung up for what seemed like an eternity and what was probably closer to fifteen minutes. Our issue specifically had to do with error handling in Django Rest Framework. It ended up, as it usually does, being just a dumb little mistake. Unfortunately, there were some somewhat unclear docs that added to the confusion (which will hopefully be remedied soon).

We were trying to verify when an error in our code would occur we would not respond with the generic 500 page, but instead respond with a useful json payload containing error information. Since getting back an HTML page when you’re expecting to receive json will make you have a bad time, we wanted to make sure our API would behave in less than ideal situations.

Unfortunately for us we were in fact getting back the generic 500 error HTML page. According to Django Rest Framework’s documentation, this should not have been happening. Finally, on a whim, we changed our View object to subclass rest_framework.views.APIView instead of rest_framework.views.View. That one simple little change fixed everything.

After some investigation it turns out that rest_framework.views.View is really just something that is internal to Django Rest Framework and, in our scenario, turned out to be the exact same thing as django.views.generic.View. View from rest_framework.views is actually imported into rest_framework.views from rest_framework.compat which imports View from django.views.generic.

Maybe this is a side effect of the way that Python imports work. Anything defined at the top level of a python module (or imported into the top level of a Python module) is importable by anyone. There are a few ways to “hide” things that you are importing if you do not want them to be a part of your module’s API, but I haven’t seen anything that I really like. I do, however, like how Node.js modules deal with exporting, it is much more explicit - which seems to fit Python’s style fairly well.