web-dev-qa-db-fra.com

Obtenir les champs de modèles à Django

Avec un modèle Django, j'essaie de lister tous ses champs. J'ai déjà vu quelques exemples d'utilisation de l'attribut de modèle _meta, mais le trait de soulignement situé devant la méta n'indique-t-il pas que l'attribut _meta est un attribut privé et ne doit pas être consulté directement? ... Parce que, par exemple, la présentation de _meta pourrait changer à l'avenir et ne pas être une API stable? 

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

Tout conseil est fort apprécié. 

 Objet Django get/set field

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

Comment introspecter les champs du modèle Django?

96
Joe J

_meta est privé, mais relativement stable. Des efforts ont été faits pour le formaliser, le documenter et supprimer le trait de soulignement, ce qui pourrait arriver avant les versions 1.3 ou 1.4. J'imagine que des efforts seront faits pour garantir une compatibilité ascendante, car de nombreuses personnes l'utilisent de toute façon.

Si la compatibilité vous préoccupe particulièrement, écrivez une fonction qui prend un modèle et renvoie les champs. Cela signifie que si quelque chose change dans le futur, il vous suffit de changer une fonction.

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

Je pense que cela renverra une liste d'objets Field. 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 code Google Summer of Code. Voir:
- https://groups.google.com/forum/#!topic/Django-developers/hD4roZq0wyk
- https://code.djangoproject.com/wiki/new_meta_api

129
Will Hardy

Je sais que ce message est assez ancien, mais je voulais juste dire à ceux qui recherchent la même chose qu’il existe une API publique et officielle de le faire: get_fields() et get_field()

Usage:

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

https://docs.djangoproject.com/fr/1.8/ref/models/meta/

76
PirosB3

C'est ce que Django lui-même fait 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 Django.forms.models.fields_for_model, voici comment procéder:

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

Maintenant, il existe une méthode spéciale - get_fields ()

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

Il accepte deux paramètres qui peuvent être utilisés pour contrôler les champs retournés:

  • include_parents

    Vrai par défaut. Inclut de manière récursive les champs définis sur les classes parent. Si la valeur est False, get_fields () recherchera uniquement les champs déclarés directement sur le modèle actuel. Les champs de modèles qui héritent directement de modèles abstraits ou de classes proxy sont considérés comme locaux, pas sur le parent.

  • include_hidden

    Faux par défaut Si défini sur True, get_fields () inclura les champs utilisés pour sauvegarder les fonctionnalités des autres champs. Cela inclura également tous les champs ayant un related_name (comme ManyToManyField ou ForeignKey) qui commencent par un "+"

5
pecos pest

Les champs de modèle contenus par _meta sont répertoriés dans plusieurs emplacements en tant que listes des objets de champ respectifs. Il peut être plus facile de travailler avec eux comme un dictionnaire où les clés sont les noms de champs.

À mon avis, c'est le moyen le plus irrédondant et le plus expressif de collecter et d'organiser les objets de champ modèle:

def get_model_fields(model):
  fields = {}
  options = model._meta
  for field in sorted(options.concrete_fields + options.many_to_many + options.virtual_fields):
    fields[field.name] = field
  return fields

(Voir Cet exemple d'utilisation dans Django.forms.models.fields_for_model.)

4
jxqz

get_fields() renvoie une Tuple et chaque élément est un type Model field, qui ne peut pas être utilisé directement en tant que chaîne. Donc, field.name renverra le nom du champ

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

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']
3
JPG

Celui-ci, ça va.

fields = Model._meta.fields
2
JDE876

Selon la documentation de Django 2.2, vous pouvez utiliser:

Pour obtenir tous les champs: Model._meta.get_fields()

Pour obtenir un champ individuel: Model._meta.get_field('field name')

ex. Session._meta.get_field('expire_date')

1
chirag

Si vous en avez besoin pour votre site admin, il existe également la méthode ModelAdmin.get_fields ( docs ), qui renvoie list du nom du champ strings.

Par exemple:

class MyModelAdmin(admin.ModelAdmin):
    # extending change_view, just as an example
    def change_view(self, request, object_id=None, form_url='', extra_context=None):
        # get the model field names
        field_names = self.get_fields(request)
        # use the field names
        ...
0
djvg