django: best practice way to get model from an instance of that model
DjangoDjango Problem Overview
Say my_instance
is of model MyModel
.
I'm looking for a good way to do:
my_model = get_model_for_instance(my_instance)
I have not found any really direct way to do this. So far I have come up with this:
from django.db.models import get_model
my_model = get_model(my_instance._meta.app_label, my_instance.__class__.__name__)
Is this acceptable? Is it even a sure-fire, best practice way to do it?
There is also _meta.object_name
which seems to deliver the same as __class__.__name__
. Does it? Is better or worse? If so, why?
Also, how do I know I'm getting the correct model if the app label occurs multiple times within the scope of the project, e.g. 'auth' from 'django.contrib.auth' and let there also be 'myproject.auth'?
Would such a case make get_model
unreliable?
Thanks for any hints/pointers and sharing of experience!
Django Solutions
Solution 1 - Django
my_model = type(my_instance)
To prove it, you can create another instance:
my_new_instance = type(my_instance)()
This is why there's no direct way of doing it, because python objects already have this feature.
updated...
I liked marcinn's response that uses type(x)
. This is identical to what the original answer used (x.__class__
), but I prefer using functions over accessing magic attribtues. In this manner, I prefer using vars(x)
to x.__dict__
, len(x)
to x.__len__
and so on.
updated 2...
For deferred instances (mentioned by @Cerin in comments) you can access the original class via instance._meta.proxy_for_model
.
Solution 2 - Django
my_new_instance = type(my_instance)()
Solution 3 - Django
At least for Django 1.11, this should work (also for deferred instances):
def get_model_for_instance(instance):
return instance._meta.model