235 votes

Comment fonctionne la classe Meta imbriquée de Django ?

J'utilise Django qui permet aux gens d'ajouter des paramètres supplémentaires à une classe en utilisant class Meta .

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

La seule chose que j'ai trouvée dans la documentation de Python est :

class FooMetaClass(type):
    ...

class FooClass:
    __metaclass__ = FooMetaClass

Cependant, je ne pense pas que ce soit la même chose.

6 votes

Le titre pose la question de la méta Python, mais la question semble porter sur la méta Django - sur laquelle porte votre question ?

22 votes

@ckhan il est confus à cause de la décision absurde (IMO) d'appeler une classe imbriquée "Meta", ce qui est très trompeur ; pour les débutants, sur les métaclasses de Python, et pour les utilisateurs plus expérimentés qui ne l'ont jamais vu, sur son but a priori (au lieu d'utiliser des attributs de classe ou de vraies métaclasses)

287voto

Tadeck Points 37046

Vous posez une question sur deux choses différentes :

  1. Meta classe interne dans les modèles Django :

    Il s'agit simplement d'un conteneur de classe avec quelques options (métadonnées) attachées au modèle. Elles définissent des éléments tels que les permissions disponibles, le nom de la table de base de données associée, si le modèle est abstrait ou non, les versions singulière et plurielle du nom, etc.

    L'explication succincte est ici : Docs Django : Modèles : Options méta

    La liste des options méta disponibles est ici : Docs Django : Options de méta-modèles

    Pour la dernière version de Django : Docs Django : Options de méta-modèles

  2. Métaclasse en Python :

    La meilleure description est ici : Que sont les métaclasses en Python ?

3 votes

Ces deux choses sont-elles liées ? Par exemple, est-ce que la fonction Meta vous empêche d'utiliser les fonctions de métaclasses intégrées de Python ?

12 votes

@nnyby : Il y a deux choses qui créent une relation entre ces deux concepts : le nom et la confusion que beaucoup d'utilisateurs ont (comme le PO l'avait dans sa question originale). Je pense qu'aborder cette confusion commune est un avantage significatif de ce topi. N'êtes-vous pas d'accord ?

59voto

Paul Whipp Points 2868

Dans le prolongement de la réponse de Tadeck à propos de Django, l'utilisation de 'class Meta:' dans Django est aussi du Python normal.

La classe interne est un espace de nom pratique pour les données partagées entre les instances de la classe (d'où le nom Meta pour "métadonnées", mais vous pouvez l'appeler comme vous le souhaitez). Bien que dans Django il s'agisse généralement d'éléments de configuration en lecture seule, rien ne vous empêche de les modifier :

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

Vous pouvez également l'explorer directement dans Django, par exemple :

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

Cependant, dans Django, il est plus probable que vous souhaitiez explorer la section _meta qui est un Options objet créé par le modèle metaclass lorsqu'un modèle est créé. C'est là que vous trouverez toutes les informations "méta" de la classe Django. Dans Django, Meta est juste utilisé pour passer des informations dans le processus de création de la _meta Options objet.

0 votes

Cela ne fonctionne pas sur les modèles définis par l'utilisateur : >>>from myapp.models import MyModel >>>MyModel.Meta Traceback (most recent call last) : File "<console>", line 1, in <module> AttributeError : type object 'MyModel' has no attribute 'meta'.

2 votes

Vous avez besoin de l'underscore, par exemple. MyUser.objects.get(pk=1)._meta

0 votes

Exact, mais cela n'accède pas à la classe Meta interne de la classe du modèle. Cela permet d'accéder aux options _meta pour l'instance de ce modèle... il ne semble pas y avoir de moyen d'accéder à la classe Meta interne elle-même. Le cas d'utilisation pour moi était la sous-classification d'une classe proxy MyModelProxy à partir de MyModel de telle sorte que MyModelProxy puisse hériter de la classe Meta interne de MyModel.

26voto

Amber Points 159296

Le programme de Django Model gère spécifiquement le fait d'avoir un attribut nommé Meta qui est une classe. Ce n'est pas un truc général de Python.

Les métaclasses Python sont complètement différentes.

17 votes

Je pense que votre réponse n'est pas assez claire - pourriez-vous développer comment Meta La classe fonctionne ? Je crois que l'OP a demandé spécifiquement à ce sujet.

14voto

jhrr Points 893

Les réponses qui affirment que le modèle Django Meta et les métaclasses sont "complètement différentes" sont des réponses trompeuses.

La construction du modèle Django objets de la classe c'est-à-dire l'objet qui représente la définition de la classe elle-même (oui, les classes sont aussi des objets), sont en effet contrôlés par une métaclasse appelée ModelBase et vous pouvez voir ce code ici .

Et une des choses que ModelBase consiste à créer le _meta sur chaque modèle Django qui contient les mécanismes de validation, les détails des champs, la logique de sauvegarde, etc. Au cours de cette opération, les éléments spécifiés dans l'attribut interne du modèle Meta est lue et utilisée dans le cadre de ce processus.

Donc, bien que oui, dans un sens Meta et les métaclasses sont des "choses" différentes, mais elles sont intimement liées dans la mécanique de construction des modèles de Django ; comprendre comment elles fonctionnent ensemble vous permettra d'approfondir votre compréhension des deux.

Cela peut être une source d'information utile pour mieux comprendre comment les modèles Django utilisent les métaclasses.

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

Et cela peut aussi vous aider si vous voulez mieux comprendre le fonctionnement des objets en général.

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

3voto

Sujeet Points 21

Inner Meta Class Document :

Ce document de django Les métadonnées du modèle sont "tout ce qui n'est pas un champ", comme les options de commande. (ordering), database table name (db_table), or human-readable singular and plural names (verbose_name and verbose_name_plural) . Aucune n'est obligatoire, et l'ajout de la classe Meta à un modèle est totalement facultatif. https://docs.djangoproject.com/en/dev/topics/db/models/#meta-options

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X