Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django - Why are variables declared in Model Classes Static

Tags:

python

django

I have been reading and working with Django for a bit now. One of the things that I am still confused with is why the model classes that we create in Django are made up of static variables and not member variables. For instance

class Album(models.Model):
    artist = models.CharField(max_length=128, unique=True)
    title = models.CharField(max_length=128, unique=True)
    genre = models.CharField(max_length=128, unique=True)

    def __unicode__(self):
        return self.name 

I read this page here which explains static and instance variables in python however i am still confused as to why Django wants the field variables in models be static ?

like image 275
James Franco Avatar asked Sep 16 '16 19:09

James Franco


People also ask

What does declaring a variable static do?

Static Variables: When a variable is declared as static, then a single copy of the variable is created and shared among all objects at a class level. Static variables are, essentially, global variables. All instances of the class share the same static variable.

Are class variables static in Python?

Yes. The absence of the keyword "static" might be misleading, but any object initialised inside the class (just one indent inside the class, and not in the constructor) is static.

What are static variables in Python?

When we declare a variable inside a class but outside any method, it is called as class or static variable in python. Class or static variable can be referred through a class but not directly through an instance.

What is the difference between instance and static variable?

Instance variables are created when an object is created with the use of the keyword 'new' and destroyed when the object is destroyed. Static variables are created when the program starts and destroyed when the program stops. Instance variables can be accessed directly by calling the variable name inside the class.


1 Answers

Django uses a metaclass to create the model class. Just as a class's __init__() method creates a new instance, the metaclass's __new__() method creates the class itself. All variables, functions, properties, etc. defined in the class body are passed to the __new__() function. Strictly speaking, just defining a variable in the class body does not create a static/class variable -- only when the __new__() function receives the variable and sets it on the class, will it be a class/static variable.

Django overrides this behavior when it comes to fields and the special Meta inner class, by providing a custom __new__() method. The options in the inner Meta class are converted to an Options instance, and that instance is stored as Model._meta rather than Model.Meta. Similarly, any fields you define are stored in Model._meta.fields rather than as class/static variables.

You will notice that in your example, the class Album does not have a artist attribute: Album.artist will simply raise an AttributeError. This is because the metaclass moves the field from the class to Album._meta.fields. Instances of Album do have an artists attribute, but this is not the field. Instead, it's the database value related to the field. The __init__ method of a model uses self._meta.fields to populate any attributes with either the value that is passed to __init__, or with the default value, to assure that the instance variable exists.

Only class variables are passed to the __new__ method. If you were to define a field as an instance variable inside __init__, the field would never be passed to Model._meta.fields, and Django simply doesn't know about the field. You will be able to access Album.artist, but this will be the actual field instance, not the related database value. Basically you would be missing the magic that makes a model into a model.

like image 87
knbk Avatar answered Oct 07 '22 09:10

knbk