So I can create Django model like this:
from django.db import models
class Something(models.Model):
title = models.TextField(max_length=200)
python is extremely powerfull and permit the developer to use intrespection.
django use a lot of metaclass. and it seem that models.Model use it too. see in django\db\models\base.py
class Model(object):
__metaclass__ = ModelBase
i think the metaclass just take the classes attributes such a the Field and for all new instance for these Model subclass,create the apropriate variable.
1) yes, django create the instance variable of property "title" automaticaly 2) in the same way, the metaclass move the fields into the meta class...
I think its hard to beat what Django documentation has to say on this.
The Model class (see base.py) has a metaclass attribute that defines ModelBase (also in base.py) as the class to use for creating new classes. So ModelBase.new is called to create this new Example class. It is important to realise that we are creating the class object here, not an instance of it. In other words, Python is creating the thing that will eventually be bound to the Example name in our current namespace.
Basically a metaclass defines how a class itself will be created. During creation, additional attributes/methods/anything can be bound to that class. The example this stackoverflow answer gives, capitalizes all the attributes of a class
# remember that `type` is actually a class like `str` and `int`
# so you can inherit from it
class UpperAttrMetaclass(type):
# __new__ is the method called before __init__
# it's the method that creates the object and returns it
# while __init__ just initializes the object passed as parameter
# you rarely use __new__, except when you want to control how the object
# is created.
# here the created object is the class, and we want to customize it
# so we override __new__
# you can do some stuff in __init__ too if you wish
# some advanced use involves overriding __call__ as well, but we won't
# see this
def __new__(upperattr_metaclass, future_class_name,
future_class_parents, future_class_attr):
attrs = ((name, value) for name, value in future_class_attr.items() if not name.startswith('__'))
uppercase_attr = dict((name.upper(), value) for name, value in attrs)
return type(future_class_name, future_class_parents, uppercase_attr)
In a similar way, Django's metaclass for Models can digest the attributes you've applied to the class and add various useful attributes for validation/etc, including even methods and what-not.