Is there any downside to using something like
from django.db.models.loading import get_model
def get_something():
model = get_model('app', 'Model')
return model.something()
instead of
from app.models import Model
def get_something():
return Model.something()
The second example can lead to circular dependencies while the first example does not, but the second example is seen much more often.
Update: You would get circular dependency errors if the second example was in a model called Other_Model and Model imported Other_Model as well -- a simple circular import.
Generally, the get_model
functionality is reserved for times when a model needs to be loaded dynamically (say, if you don't know if someone will pass a service a myapp.Person, a myapp.Place, or a myapp.Thing and they all have the same interface). I will go so far as to say that any other use should be auto-flagged in code review if for no other reason than the fact that it introduces the unexpected.
As to internal mechanics, there really isn't a substantial difference. Inevitably the get_model
version will call __import__
. That said, it is not without bugs. Use of actual import
statements will avoid this problem.
As to MRO issues, it is a rare situation where circular imports could not be resolved by refactoring. If you have two apps which are so interdependent that they cause a circular import, then you really need to re-think those apps. (My guess is that you are really dealing with one app.)
Using get_model
may be confusing if your app path is not so straight forward.
For example, if your model exists in apps.MyApp.models.misc.MyModel
, then the call would be get_model('MyApp', 'misc.MyModel')
which isn't too intuitive. You'll probably have to figure it out by trial and error or digging into the source.
(Note that this applies for Django 1.6 and before. Django 1.7+ has a lot of changes to the app naming and this may have changed)
Another way to avoid circular dependencies is to do the import directly in the method like so:
def get_something():
from app.models import Model
return Model.something()
This will defer the import until the first invocation of the method.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With