2👍
I get that models is a class with methods such as CharField(), which is being inherited into these classes in order to create table columns…right?
I believe you took a wrong turn at Albuquerque. Lowercase models
is not a class and CharField()
is not a method, though it does end up calling a particular method called __init__()
but we’ll get to that in a bit.
First, look at the import statement:
from django.db import models
Lowercase models
here is a package, meaning it is a directory containing an __init__.py
file. Specifically, it is a sub-package of the package db
, which is itself a sub-package of the django
package. The Python dotted path parallels the package directory structure.
It is worth noting here that models
is NOT a module, though it COULD have been. If there were a Python file named models.py
within the db
package, then models
would have been a module. How do we know for sure? By perusing the Django source code, we find that it is a directory, and thus a package. See the source code here.
So, packages are directories containing either: other directories (sub-packages) or python files (modules). Class definitions are defined in the modules. Ok, then how is the Model
class imported from models
if it is a package and not a module?
This is possible because the __init__.py
file in the models
package imports the Model
class. The Model
class definition actually lives in the base
module, yep the base.py
file within the models
package.
Now, for the CharField()
. In Python, class instantiation uses the function notation. When defining your custom Model
classes, the database fields are created from your model’s class attributes. Within the Book
model, title
is a class attribute, instantiated from the CharField
class. When it is instantiated, the CharField
method __init__()
is called.
And here is a good place to point out why it is handy to have packages for making imports more convenient. The CharField
class is defined within the fields
sub-package of the models
package, and many of Django’s other field classes are defined there as well. Similar to how __init__.py
in the models
package imported the Model
class from the base
sub-module, it also imports all the fields from the fields
sub-module.
Since the models
package takes care of all the sub-imports we’ll likely need to use, we can just import that package. Using the from
style import, we can easily identify all the places in our code where we are using something from that package, since it always has the dot notation models.Something
. We don’t have to worry about how all that stuff is organized in the package.
For more details, see the Python documentation on packages.