172 votes

Récupérer les champs du modèle dans Django

Étant donné un modèle Django, j'essaie de lister tous ses champs. J'ai vu quelques exemples pour faire cela en utilisant l'attribut de modèle _meta, mais le trait de soulignement devant meta n'indique-t-il pas que l'attribut _meta est un attribut privé et qu'il ne faut pas y accéder directement ? ... Parce que, par exemple, la disposition de _meta pourrait changer à l'avenir et ne pas constituer une API stable ?

Est-ce que _meta est une exception à cette règle ? Est-il stable et prêt à être utilisé ou est-il considéré comme une mauvaise pratique d'y accéder ? Ou existe-t-il une fonction ou un autre moyen d'introspecter les champs d'un modèle sans utiliser l'attribut _meta ? Vous trouverez ci-dessous une liste de liens montrant comment procéder en utilisant l'attribut _meta.

Tout conseil est le bienvenu.

champ get/set d'un objet django

http://www.djangofoo.com/80/get-list-model-fields

Comment introspecter les champs d'un modèle django ?

0 votes

201voto

Will Hardy Points 6663

_meta est privée, mais elle est relativement stable. Des efforts sont faits pour le formaliser, le documenter et supprimer le trait de soulignement, ce qui pourrait se produire avant la 1.3 ou la 1.4. J'imagine que des efforts seront faits pour s'assurer que les choses sont rétrocompatibles, parce que beaucoup de gens l'ont utilisé de toute façon.

Si vous êtes particulièrement soucieux de la compatibilité, écrivez une fonction qui prend un modèle et renvoie les champs. Ainsi, si quelque chose change à l'avenir, vous n'aurez à modifier qu'une seule fonction.

def get_model_fields(model):
    return model._meta.fields

Je pense que cela renverra une liste de Field objets. Pour obtenir la valeur de chaque champ de l'instance, utilisez getattr(instance, field.name) .

Mise à jour : les contributeurs de Django travaillent sur une API pour remplacer l'objet _Meta dans le cadre d'un Google Summer of Code. Voir :
- https://groups.google.com/forum/#!topic/django-developers/hD4roZq0wyk
- https://code.djangoproject.com/wiki/new_meta_api

53 votes

Vous devez également être conscient du fait que si vous avez également besoin des champs many-to-many, vous devez accéder à model._meta.many_to_many !

1 votes

Merci Will. Il est bon de savoir que d'autres personnes utilisent également _meta. J'aime l'idée d'avoir une fonction d'encapsulation. Lazerscience, merci également. C'est bien de savoir qu'il existe une bonne méthode pour obtenir les champs many_to_many. Joe

1 votes

Def get_model_fields(self) : return self._meta.fields utilisé ceci pour retourner facilement tous les champs du modèle... Merci beaucoup...

149voto

PirosB3 Points 182

Je sais que ce message est assez ancien, mais je tenais à dire à tous ceux qui cherchent la même chose qu'il existe une API publique et officielle pour le faire : get_fields() y get_field()

Utilisation :

fields = model._meta.get_fields()
my_field = model._meta.get_field('my_field')

https://docs.djangoproject.com/en/3.2/ref/models/meta/#retrieving-all-field-instances-of-a-model

24voto

JPG Points 11863

get_fields() renvoie un tuple et chaque élément est un Model field qui ne peut pas être utilisé directement comme une chaîne de caractères. Donc, field.name retournera le nom du champ

my_model_fields = [field.name for field in MyModel._meta.get_fields()]
Le code ci-dessus retournera une liste contenant le nom de tous les champs.

Exemple

In [11]: from django.contrib.auth.models import User

In [12]: User._meta.get_fields()
Out[12]: 
(<ManyToOneRel: admin.logentry>,
 <django.db.models.fields.AutoField: id>,
 <django.db.models.fields.CharField: password>,
 <django.db.models.fields.DateTimeField: last_login>,
 <django.db.models.fields.BooleanField: is_superuser>,
 <django.db.models.fields.CharField: username>,
 <django.db.models.fields.CharField: first_name>,
 <django.db.models.fields.CharField: last_name>,
 <django.db.models.fields.EmailField: email>,
 <django.db.models.fields.BooleanField: is_staff>,
 <django.db.models.fields.BooleanField: is_active>,
 <django.db.models.fields.DateTimeField: date_joined>,
 <django.db.models.fields.related.ManyToManyField: groups>,
 <django.db.models.fields.related.ManyToManyField: user_permissions>)

In [13]: [field.name for field in User._meta.get_fields()]
Out[13]: 
['logentry',
 'id',
 'password',
 'last_login',
 'is_superuser',
 'username',
 'first_name',
 'last_name',
 'email',
 'is_staff',
 'is_active',
 'date_joined',
 'groups',
 'user_permissions']

16voto

pecos pest Points 564

Maintenant il y a une méthode spéciale - get_fields()

    >>> from django.contrib.auth.models import User
    >>> User._meta.get_fields()

Elle accepte deux paramètres qui peuvent être utilisés pour contrôler les champs qui sont renvoyés :

  • inclure_parents

    Vrai par défaut. Inclut récursivement les champs définis sur les classes parentes. Si la valeur est False, get_fields() ne recherchera que les champs déclarés directement sur le modèle courant. Les champs des modèles qui héritent directement de modèles abstraits ou de classes proxy sont considérés comme étant locaux, et non sur le parent.

  • inclure_caché

    Faux par défaut. Si la valeur est True, get_fields() inclura les champs qui sont utilisés pour soutenir la fonctionnalité d'autres champs. Cela inclura également tous les champs qui ont un related_name (comme ManyToManyField ou ForeignKey) et qui commencent par un "+".

10voto

ecstaticpeon Points 148

C'est quelque chose qui est fait par Django lui-même lorsqu'il construit un formulaire à partir d'un modèle. Il utilise l'attribut _meta, mais comme Bernhard l'a noté, il utilise à la fois _meta.fields et _meta.many_to_many. En regardant dans django.forms.models.fields_for_model, voici comment vous pourriez le faire :

opts = model._meta
for f in sorted(opts.fields + opts.many_to_many):
    print '%s: %s' % (f.name, f)

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