278 | | If Restaurant were to inherit from this, it would not automatically have a 'name' CharField. This is because Django uses a metaclass to modify the default class creation behavior. The ModelBase metaclass creates a new class from scratch, and then selectively pulls items from the Place class as defined above and adds them to this new class, which allows it to handle Field objects specially. For each of the class's attributes, add_to_class() is called. If add_to_class finds a 'contribute_to_class' attribute, ModelBase knows it is dealing with a Field object, and calls contribute_to_class. Otherwise, it just adds it to the new class via setattr(). |
279 | | Thus, by the time the Restaurant class is created, the Place class which it inherits from actually looks more like this: |
| 278 | If Restaurant were to inherit from this, it would not automatically have a 'name' `CharField`. This is because Django uses a metaclass to modify the default class creation behavior. The `ModelBase` metaclass creates a new class from scratch, and then selectively pulls items from the Place class as defined above and adds them to this new class, which allows it to handle `Field` objects specially. For each of the class's attributes, add_to_class() is called. If add_to_class finds a 'contribute_to_class' attribute, `ModelBase` knows it is dealing with a `Field` object, and calls contribute_to_class. Otherwise, it just adds it to the new class via setattr(). |
| 279 | Thus, by the time the `Restaurant` class is created, the `Place` class which it inherits from actually looks more like this: |
289 | | Thus, there is simply no 'name' field for it to inherit. So, we need to have ModelBase walk through the parent classes and call contribute_to_class on each of the fields found in _meta.fields. As we walk the inheritance tree, we look for a '_meta' attribute to determine if our current node is a Model. Otherwise, it is either a mixin class or the Model class iteself. |
290 | | |
291 | | We can keep track of the parent hierarchy by creating _meta.parents, and having each ancestor of Model add to it in a recursive fasion, by adding the following to ModelBase.__new__(): |
| 289 | Thus, there is simply no 'name' field for it to inherit. So, we need to have `ModelBase` walk through the parent classes and call contribute_to_class on each of the fields found in _meta.fields. As we walk the inheritance tree, we look for a '_meta' attribute to determine if our current node is a `Model`. Otherwise, it is either a mixin class or the `Model` class itself. |
| 290 | |
| 291 | We can keep track of the parent hierarchy by creating _meta.parents, and having each ancestor of Model add to it in a recursive fashion, by adding the following to `ModelBase`.__new__(): |