2012-04-27 21 views
115

Estoy usando Django que permite a las personas agregar parámetros extra a una clase usando class Meta.¿Cómo funciona la clase Meta de Django?

class FooModel(models.Model): 
    ... 
    class Meta: 
     ... 

El único que he encontrado en la documentación de Python fue:

class FooMetaClass(type): 
    ... 

class FooClass: 
    __metaclass__ = FooMetaClass 

Sin embargo, no creo que esto es lo mismo.

+3

Título pregunta sobre Python meta, pero parece cuestión de preguntar acerca de Django meta - que se lo preguntas acerca? – ckhan

Respuesta

145

Usted está haciendo una pregunta de dos cosas diferentes:

  1. Meta clase interna en modelos de Django:

    Esto es sólo un contenedor clase con algunas opciones (metadatos) unidos al modelo . En él se definen las cosas tales como permisos disponibles, asociado nombre de la tabla de base de datos, si el modelo es abstracto o no, singular y plural versiones del nombre etc.

    Breve explicación está aquí: Django docs: Models: Meta options

    lista de opciones disponibles es meta aquí: Django docs: Model Meta options

  2. MetaClass en Python:

    La mejor descripción es aquí: What is a metaclass in Python?

+1

¿Están estas dos cosas relacionadas en absoluto? es decir, ¿la clase interna 'Meta' de Django le impide usar las características incorporadas de la metaclase de Python? – nnyby

+7

@nnyby: hay dos cosas que crean una relación entre estos dos conceptos: nombre y confusión que tienen muchos usuarios (como OP lo tenía en la pregunta original). Creo que abordar esa confusión común es una ventaja significativa de este topi. ¿No estás de acuerdo? – Tadeck

19

La clase Model de Django maneja específicamente tener un atributo llamado Meta que es una clase. No es una cosa general de Python.

Las metaclases de Python son completamente diferentes.

+11

Creo que tu respuesta no es lo suficientemente clara, ¿podrías explicar cómo funciona la clase 'Meta'? Creo que OP preguntó específicamente sobre eso. – Tadeck

34

Extendiendo la respuesta Django de Tadeck anterior, el uso de la 'clase Meta:' en Django también es normal en Python.

La clase interna es un espacio de nombres conveniente para datos compartidos entre las instancias de clases (de ahí el nombre Meta para 'metadatos' pero puede llamarlo como quiera). Mientras que en Django es generalmente de sólo lectura cosas configuración, no hay nada que le impida cambiarlo:

In [1]: class Foo(object): 
    ...:  class Meta: 
    ...:   metaVal = 1 
    ...:   
In [2]: f1 = Foo() 
In [3]: f2 = Foo() 
In [4]: f1.Meta.metaVal 
Out[4]: 1 
In [5]: f2.Meta.metaVal = 2 
In [6]: f1.Meta.metaVal 
Out[6]: 2 
In [7]: Foo.Meta.metaVal 
Out[7]: 2 

se puede explorar en Django directamente también por ejemplo:

In [1]: from django.contrib.auth.models import User 
In [2]: User.Meta 
Out[2]: django.contrib.auth.models.Meta 
In [3]: User.Meta.__dict__ 
Out[3]: 
{'__doc__': None, 
'__module__': 'django.contrib.auth.models', 
'abstract': False, 
'verbose_name': <django.utils.functional.__proxy__ at 0x26a6610>, 
'verbose_name_plural': <django.utils.functional.__proxy__ at 0x26a6650>} 

Sin embargo, en Django es más es probable que desee explorar el atributo _meta, que es un objeto Opciones creado por la metaclase del modelo cuando se crea un modelo. Ahí es donde encontrarás toda la información de metadatos de la clase django. En Django, Meta solo se usa para pasar información al proceso de creación del objeto _meta Options.

+0

Esto no funciona en los modelos definidos por el usuario: >>> myapp.models de importación MyModel >>> MyModel.Meta Rastreo (llamada más reciente pasado): Archivo "", línea 1, en AttributeError: tipo objeto 'MyModel' no tiene atributo 'meta' – bdf

+0

Necesita el guión bajo, por ejemplo, 'MyUser.objects.get (pk = 1) ._ meta' –

+0

Correcto, pero eso no tiene acceso a la clase Meta interna de la clase del Modelo. Eso accede a las opciones de _meta para la instancia de ese Modelo ... no parece haber una manera de acceder a la clase Meta interna. El caso de uso para mí estaba subclasificando una clase proxy MyModelProxy de MyModel de forma que MyModelProxy puede heredar la clase Meta interna de MyModel. – bdf

1

Las respuestas que afirman que el modelo Meta de Django y las "metaclases" son "completamente diferentes" son respuestas engañosas.

La construcción del modelo de Django clase de objetos (es decir, el objeto que representa la definición de clase en sí) son efectivamente controlado por una metaclase llamada ModelBase, se puede ver que el código aquí:

https://github.com/django/django/blob/master/django/db/models/base.py#L61

Y una de las cosas que hace ModelBase es crear el atributo _meta en cada modelo de Django que contiene maquinaria de validación, detalles de campo, maquinaria de guardado, etc. Y, durante esta operación, todo lo que se especifica en la clase interna Meta del modelo se lee y utiliza dentro de ese proceso.

Entonces, mientras que sí, en cierto sentido Meta y las metaclases son diferentes 'cosas', dentro de la mecánica de la construcción del modelo de Django están íntimamente relacionadas; entender cómo trabajan juntos profundizará su visión de ambos a la vez.

Esta podría ser una fuente útil de información para comprender mejor cómo los modelos Django emplean metaclases.

https://code.djangoproject.com/wiki/DevModelCreation

Y esto podría ayudar también si se quiere entender mejor cómo funcionan los objetos en general.

https://docs.python.org/3/reference/datamodel.html

Cuestiones relacionadas