2009-02-01 14 views
10

Antes que nada, no estoy en la programación web. Choqué con django y leí un poco sobre modelos. Yo estaba intrigado por el siguiente código (de djangoproject.com):¿Cómo funcionan los campos de modelo de Django?


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

Por mi comprensión de pitón, nombre apellido y apellidos son variables de clase, ¿verdad? ¿Cómo se usa eso en el código (porque supongo que establecer Person.first_name o Person.last_name afectará a todas las instancias de Person)? ¿Por qué se usa de esa manera?

Respuesta

4

Sí, first_name y last_name son variables de clase. Definen los campos que se crearán en una tabla de base de datos. Hay una tabla Person que tiene columnas first_name y last_name, por lo que tiene sentido que estén en el nivel Class en este punto.

Para más información sobre modelos, ver: http://docs.djangoproject.com/en/dev/topics/db/models/

Cuando se trata de acceder a instancias de una persona en el código, que normalmente están haciendo esto a través de ORM de Django, y en este punto que en esencia se comportan como variables de instancia.

Para más información sobre instancias de modelo, véase: http://docs.djangoproject.com/en/dev/ref/models/instances/?from=olddocs

+0

Danke Schon Andy! – Geo

+0

Algunos buenos enlaces aquí, pero "en este punto se comportan esencialmente como variables de instancia" es un poco de agitar la mano que no es realmente precisa (o al menos no explica nada). –

+1

Lo suficientemente justo ... Levantaré mis manos hacia esa. +1 en tu respuesta. :) –

19

La esencia de su pregunta es "¿cómo es que estas variables de clase (que le asigno objetos Field a) de repente se convierten en variables de instancia (que le asigno datos a) en ¿ORM de Django? La respuesta a eso es la magia de Python metaclasses.

Una metaclase le permite enganchar y modificar el proceso de creación de una clase de Python (no la creación de una instancia de esa clase, la creación de la misma clase).

Objeto de modelo de Django (y por lo tanto también sus modelos, que son subclases) tiene un ModelBase metaclass. Se ve a través de todos los atributos de clase de su modelo, y cualquiera que sean instancias de una subclase de campo se mueve a una lista de campos. Esa lista se asigna como un atributo del objeto _meta, que es un atributo de clase del modelo. Por lo tanto, siempre puede acceder a los objetos de campo reales a través del MyModel._meta.fields, o MyModel._meta.get_field('field_name').

El método Model.__init__ es capaz de utilizar la lista _meta.fields para determinar qué atributos de instancia se deben inicializar cuando se crea una instancia de modelo.

No tenga miedo de sumergirse en el código fuente de Django; ¡es una gran fuente de educación!

+0

+1: Esto es genial vudú. No es algo que deberías entender profundamente. Pero necesita ver que dobla las reglas obvias de variable de instancia, agregando otra capa a la forma en que se crean los objetos. –

+0

Buena explicación. – Harold

+0

Cool. Me pregunto: ¿el atributo '_meta' es parte del API modelo oficial? – pcv

0

No es una respuesta real, pero para el enriquecimiento:

Person.first_name 

no funcionará

p = Person.objects.get(pk=x) 
p.first_name 

va a funcionar. entonces una instancia de objeto de una persona tiene un nombre y un apellido, pero el contexto estático no lo tiene.

También tenga en cuenta: Django tiene administradores de modelos que permiten a "Persona" realizar operaciones de conjunto de consultas estáticas. (https://docs.djangoproject.com/en/dev/topics/db/managers/#managers).

así por ejemplo

peoples = Person.objects.all() 
Cuestiones relacionadas