21

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"?

Ned Batchelder
378k77 gold badges583 silver badges675 bronze badges
asked Aug 17, 2012 at 12:54

2 Answers 2

17

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.

answered Aug 17, 2012 at 13:24
Sign up to request clarification or add additional context in comments.

3 Comments

Thanks for link to documentation on code.djangoproject.com! I was only searching for explanation at docs.djangoproject.com
So metacclass can add attributes, methods etc. but can it also remove attributes/methods etc. as class variable title of type CharField was clearly removed? Or wasn't it?
@Michal sure, remember all python attributes are stored in __dict__. By manipulating that __dict__ you can do pretty much anything.
2

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...

answered Aug 17, 2012 at 13:49

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.