views:

699

answers:

2

First of all,I'm not into web programming. I bumped into django and read a bit about models. I was intrigued by the following code ( from djangoproject.com ) :


class Person(models.Model):
    first_name = models.CharField(max_length=50)
    last_name = models.CharField(max_length=50)

    def __str__(self):
        # Note use of django.utils.encoding.smart_str() here because
        # first_name and last_name will be unicode strings.
        return smart_str('%s %s' % (self.first_name, self.last_name))

By my understanding of python , first_name and last_name are class variables , right ? How is that used in code ( because I guess that setting Person.first_name or Person.last_name will affect all Person instances ) ? Why is it used that way ?

+2  A: 

Yes, first_name and last_name are class variables. They define fields that will be created in a database table. There is a Person table that has first_name and last_name columns, so it makes sense for them to be at Class level at this point.

For more on models, see: http://docs.djangoproject.com/en/dev/topics/db/models/

When it comes to accessing instances of a Person in code, you are typically doing this via Django's ORM, and at this point they essentially behave as instance variables.

For more on model instances, see: http://docs.djangoproject.com/en/dev/ref/models/instances/?from=olddocs

For more on Python class variables, see: http://diveintopython.org/object_oriented_framework/class_attributes.html

Andy Hume
Danke schon Andy!
Geo
Some good links here, but "at this point they essentially behave as instance variables" is a bit of hand-waving that isn't really accurate (or at least doesn't explain anything).
Carl Meyer
Fair enough... I'll hold my hands up to that one. +1 on your answer. :)
Andy Hume
+10  A: 

The essence of your question is "how come these class variables (which I assign Field objects to) suddenly become instance variables (which I assign data to) in Django's ORM"? The answer to that is the magic of Python metaclasses.

A metaclass allows you to hook into and modify the process of creating a Python class (not the creation of an instance of that class, the creation of the class itself).

Django's Model object (and thus also your models, which are subclasses) has a ModelBase metaclass. 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._meta.fields, or MyModel._meta.get_field('field_name').

The Model.__init__ method is then able to use the _meta.fields list to determine what instance attributes should be initialized when a model instance is created.

Don't be afraid to dive into the Django source code; it's a great source of education!

Carl Meyer
+1: This is cool voodoo. It's not something you should deeply understand. But you do need to see that it bends the obvious instance variable rules, adding another layer to the way objects are created.
S.Lott
Nice explanation.
Harold