So I can create Django model like this:
from django.db import models
class Something(models.Model):
title = models.TextField(max_length=200)
and I can work with it like this:
thing = Something()
#set title
thing.title = "First thing"
#get title
thing.title
All works as it should but I'd like to understand HOW it works.
title = models.TextField(max_length=200)
in non-Django Python code above line defines class variable title of type models.TextField and I could access it also like this: thing.__class__.title
(link)
But in Django when I create instance of Something I suddenly have a title attribute where I can get/set text. And cannot access it with thing.__class__.title
So clearly when doing thing.title I'm not accessing class variable "title" but some generated attribute/property, or?
I know that fields ended up in thing._meta.fields but how? What's going on and how?
1, Does Django create property "title" behind the scenes?
2, What happened to class variable "title"?
Creating objectsTo create an object, instantiate it using keyword arguments to the model class, then call save() to save it to the database. This performs an INSERT SQL statement behind the scenes. Django doesn't hit the database until you explicitly call save() . The save() method has no return value.
A Django model is a table in your database.
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.
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