J'ai défini une classe User
qui hérite (finalement) de models.Model
. Je souhaite obtenir une liste de tous les champs définis pour ce modèle. Par exemple, phone_number = CharField(max_length=20)
. En gros, je veux récupérer tout ce qui hérite de la classe Field
.
Je pensais pouvoir les récupérer en tirant parti de inspect.getmembers(model)
, mais la liste renvoyée ne contient aucun de ces champs. Il semble que Django ait déjà saisi la classe, ajouté tous ses attributs magiques et supprimé ce qui a été défini. Alors ... comment puis-je obtenir ces champs? Ils ont probablement une fonction pour les récupérer pour leurs propres besoins internes?
Comme la plupart des réponses sont obsolètes, je vais essayer de vous mettre à jour sur Django 2.2 . Ici, vous publiez votre application (publications, blog, boutique, etc.)
1) Du modèle lien: https://docs.djangoproject.com/en/2.2/ref/models/meta/ =
from posts.model import BlogPost
all_fields = BlogPost._meta.fields
#or
all_fields = BlogPost._meta.get_fields()
Notez que:
all_fields=BlogPost._meta.get_fields()
Va aussi avoir des relations qui, par ex. vous ne pouvez pas afficher dans une vue.
Comme dans mon cas:
Organisation._meta.fields
(<Django.db.models.fields.AutoField: id>, <Django.db.models.fields.DateField: created>...
et
Organisation._meta.get_fields()
(<ManyToOneRel: crm.activity>, <Django.db.models.fields.AutoField: id>, <Django.db.models.fields.DateField: created>...
2) À partir d'instance
from posts.model import BlogPost
bp = BlogPost()
all_fields = BlogPost._meta.fields
3) Du modèle parent
Supposons que nous ayons Post comme modèle parent et que vous souhaitiez voir tous les champs d'une liste et que les champs du parent soient en lecture seule en mode Édition.
from Django.contrib import admin
from posts.model import BlogPost
@admin.register(BlogPost)
class BlogPost(admin.ModelAdmin):
all_fields = [f.name for f Organisation._meta.fields]
parent_fields = BlogPost.get_deferred_fields(BlogPost)
list_display = all_fields
read_only = parent_fields
Vous devriez utiliser get_fields()
:
[f.name for f in MyModel._meta.get_fields()]
La méthode get_all_field_names()
est obsolète à partir de Django 1.8 et sera supprimée dans 1.1 .
La page de documentation liée ci-dessus fournit une implémentation entièrement compatible avec la version antérieure de get_all_field_names()
, mais dans la plupart des cas, l'exemple précédent devrait parfaitement fonctionner.
model._meta.get_all_field_names()
Cela devrait faire l'affaire.
Cela nécessite une instance de modèle réelle. Si tout ce que vous avez est une sous-classe de Django.db.models.Model
, alors vous devriez appeler myproject.myapp.models.MyModel._meta.get_all_field_names()
La méthode get_all_related_fields()
mentionnée ici a été obsolète en 1.8 . A partir de maintenant c'est get_fields()
.
>> from Django.contrib.auth.models import User
>> User._meta.get_fields()
Il est très utile d’ajouter cela à Django modèles:
def __iter__(self):
for field_name in self._meta.get_all_field_names():
value = getattr(self, field_name, None)
yield (field_name, value)
Cela vous permet de faire:
for field, val in object:
print field, val
Cela fait l'affaire. Je ne le teste que dans Django 1.7.
your_fields = YourModel._meta.local_fields
your_field_names = [f.name for f in your_fields]
Model._meta.local_fields
ne contient pas de champs plusieurs-à-plusieurs. Vous devriez les obtenir avec Model._meta.local_many_to_many
.
def __iter__(self):
field_names = [f.name for f in self._meta.fields]
for field_name in field_names:
value = getattr(self, field_name, None)
yield (field_name, value)
Cela a fonctionné pour moi dans Django==1.11.8
Il n'est pas clair si vous avez une instance de la classe ou la classe elle-même et essayez de récupérer les champs, mais de toute façon, considérez le code suivant
en utilisant une instance
instance = User.objects.get(username="foo")
instance.__dict__ # returns a dictionary with all fields and their values
instance.__dict__.keys() # returns a dictionary with all fields
list(instance.__dict__.keys()) # returns list with all fields
tiliser une classe
User._meta.__dict__.get("fields") # returns the fields
# to get the field names consider looping over the fields and calling __str__()
for field in User._meta.__dict__.get("fields"):
field.__str__() # e.g. 'auth.User.id'
MyModel._meta.get_all_field_names()
était obsolète plusieurs versions et supprimé dans Django 1.10.
Voici la suggestion rétro-compatible de la documentation :
from itertools import chain
list(set(chain.from_iterable(
(field.name, field.attname) if hasattr(field, 'attname') else (field.name,)
for field in MyModel._meta.get_fields()
# For complete backwards compatibility, you may want to exclude
# GenericForeignKey from the results.
if not (field.many_to_one and field.related_model is None)
)))
Juste pour ajouter, j'utilise l'objet personnel, cela a fonctionné pour moi:
[f.name for f in self.model._meta.get_fields()]
Donc avant que je trouve ce post, j'ai trouvé avec succès que cela fonctionne.
Model._meta.fields
Cela fonctionne aussi bien
Model._meta.get_fields()
Je ne suis pas sûr de la différence entre les résultats, s'il en existe un. J'ai couru cette boucle et obtenu la même sortie.
for field in Model._meta.fields:
print(field.name)
Au moins avec Django 1.9.9 - la version que j'utilise actuellement -, notez que .get_fields()
"considère également" tout modèle étranger comme un champ, ce qui peut poser problème. Disons que vous avez:
class Parent(models.Model):
id = UUIDField(primary_key=True)
class Child(models.Model):
parent = models.ForeignKey(Parent)
Il s'ensuit que
>>> map(lambda field:field.name, Parent._model._meta.get_fields())
['id', 'child']
comme le montre @Rockallite
>>> map(lambda field:field.name, Parent._model._meta.local_fields)
['id']