I was learning about Python packaging, so I was looking at Django as an example of a Python package and was confused re: Why isn’t there a Model.py file since we import django.db.models.Model when we make a model?
To elaborate:
I knew from using Django that you typically do the below to make a model:
from django.db import models
class ModelName(models.Model)
...
So when I was learning about Python packaging, I looked for django/db/models/Model.py, but it doesn’t exist:
So I explored and found Model in models/__init__.py:
# Imports that would create circular imports if sorted
from django.db.models.base import DEFERRED, Model # isort:skip
which led me to django.db.models.base where I found the Model class:
class Model(AltersData, metaclass=ModelBase):
...
So that seems to answer the original question (the Model I was looking for is in base.py but imported in __init__.py for a reason related to avoiding circular imports which allows you to do models.Model without a Model.py file).
When I look at the rest of the models/__init__.py file though, it’s all imports except at the end where it defines __all__ as a list of all the imports in the file. And when I look at other __init__.py files throughout the django package, it looks like this pattern of importing other things into __init__.py files is commonly done.
But not all of the imports are under the “circular dependency” comment (most of them aren’t), and after thinking about this more, I’m thinking the comment actually isn’t explaining why Model is imported in __init__.py and instead is only explaining why those imports aren’t in the expected order for import statements.
Which brings me to my actual question: why does the django package import things in __init__.py files instead of having users import things from where they are located in the source code? E.g.
this (hypothetical):
from django.db.models.base import Model
class ModelName(Model)
...
instead of this (reality):
from django.db import models
class ModelName(models.Model)
...
For the record, I’m asking not because I have an opinion on this; I’m just trying to understand the reasoning behind putting the imports into __init__.py files – because I’m sure there’s a reason, and I just don’t understand it ( yet
).
