One cool trick to inspect live objects in your Django app with a standard Python function
Scenario: I’m writing unit tests for an API. (Which, wooooo tests.)
For ~reasons~, one of the test functions needs to loop over a list of the app’s model classes – but only the ones that get imported into views.py
for inclusion in a viewset.
Why not just hard-code the list into the test case, I hear you asking. Sure, I could do that, I’ve done worse things in my life.* But then I found the Python standard library’s inspect
function.
Some just furious Googling and a bit of shell-tinkering later, I had a two-step process outlined:
- Using
inspect.getmembers()
, fetch a list of objects in my_cool_app/views.py, passinginspect.isclass
as the predicate argument to return only classes. - Filter out anything that isn't an instance of the
django.db.models.base.ModelBase
class. (I used a list comprehension.)
Off to the races:
# from tests.py
import my_cool_app.views as mcp_views
import inspect
from django.db.models.base import ModelBase as django_mb
# inspect.getmembers() returns a tuple --> we want [1]
models_to_test = [x[1] for x in inspect.getmembers(mcp_views, inspect.isclass) if isinstance(x[1], django_mb)]
# bang bang, y'all
for my_cool_model in models_to_test:
qs = my_cool_model.objects.all()
# test test test
# test test test
# test? test!
# (spoiler, tests all passed)
Further reading:
*You have no idea.