Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django: why are Django model fields class attributes?

In Django a model's fields are defined as class attributes.

So that would mean all instances of a model would share the same values for those fields, no?

Say I have a model

class Tag(models.Model):
    name = models.CharField(max_length=30)

And I have a form in which users can submit tags. Say a user submitted 2 tags: "Python" and "Django". If I create 2 instances of Tag in my view:

t1 = Tag(name="Python")
t2 = Tag(name="Django")

Since name is a class attribute shouldn't both t1 and t2 have the same value for name which in this case should be "Django"?

But in reality name behaves like an instance attribute instead of a class attribute. Can you explain what is going on?

like image 561
Continuation Avatar asked May 10 '11 00:05

Continuation


People also ask

What are attributes in Django?

This project is an opinionated implementation of JSONField for arbitrary HTML element attributes. It aims to provide a sensible means of storing and managing arbitrary HTML element attributes for later emitting them into templates.

How do Django fields work?

It looks through all the class attributes of your model, and any that are instances of a Field subclass it moves into a fields list. That list is assigned as an attribute of the _meta object, which is a class attribute of the model. Thus you can always get to the actual Field objects via MyModel.

What class does a Django model class inherit?

The basics: Each model is a Python class that subclasses django.db.models.Model . Each attribute of the model represents a database field.


1 Answers

No, for the same reason as this:

>>> class Foo(object):
...     bar = 'Foo attribute'
...
>>> f = Foo()
>>> f.bar
'Foo attribute'
>>> Foo.bar
'Foo attribute'
>>> f.bar = 'instance attribute'
>>> f.bar
'instance attribute'
>>> Foo.bar
'Foo attribute'

When you assign an attribute to an object, a class attribute of the same name will be "eclipsed" by the object's. On attribute lookup, however, if the object in question does not define said attribute, the class one will be returned, instead.

In Django, those class attributes are used by the ORM layer to generate the mechanism that translates to SQL queries and operations (deep, metaclass magic going on behind-the-scenes).

edit: To answer your question--

To understand that, you need to understand a little bit about Python's data model. Essentially, both classes and objects have namespaces. This is apparent if you peek into their special __dict__attribute:

>>> print Foo.__dict__
{'__dict__': <attribute '__dict__' of 'Foo' objects>, '__weakref__': <attribute
'__weakref__' of 'Foo' objects>, '__module__': '__main__', 'bar': 'Foo attribute
', '__doc__': None}
>>> f = Foo()
>>> print f.__dict__
{}

When the object f is first created, it has an empty namespace. When you do a lookup, f.bar, this namespace (really, a dictionary) is looked up. Since there is no 'bar' attribute found there, f's class, Foo, is looked up. We find 'bar': 'Foo attribute' there. So that's what's going to be returned:

>>> f.bar
'Foo attribute'

Now, when you assign an attribute value to an object, and said attribute name does not yet exist in its namespace, it is created:

>>> f.bar = 'instance attribute'
>>> print f.__dict__
{'bar': 'instance attribute'}
>>> f.bar
'instance attribute'

Now, you know what happens the next time f.bar is looked up! f.__dict__['bar'] exists and will be returned before we even look at Foo's namespace.

Of course, if your intent is to always access and manipulate a class' attribute instead of the instance's, you'd need to use the class' name.

>>> Foo.bar
'Foo attribute'
>>> Foo.__dict__['bar']
'Foo attribute'
like image 100
Santa Avatar answered Oct 03 '22 10:10

Santa