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.