_meta - Django: ¿Obtener lista de campos modelo?
django model_meta (9)
Al menos con Django 1.9.9 , la versión que estoy usando actualmente, tenga en cuenta que .get_fields()
realidad también "considera" cualquier modelo extranjero como un campo, lo que puede ser problemático. Digamos que tienes:
class Parent(models.Model):
id = UUIDField(primary_key=True)
class Child(models.Model):
parent = models.ForeignKey(Parent)
Resulta que
>>> map(lambda field:field.name, Parent._model._meta.get_fields())
[''id'', ''child'']
mientras que, como se muestra por @Rockallite
>>> map(lambda field:field.name, Parent._model._meta.local_fields)
[''id'']
models.Model
una clase de User
que (en última instancia) hereda de models.Model
. Quiero obtener una lista de todos los campos definidos para este modelo. Por ejemplo, phone_number = CharField(max_length=20)
. Básicamente, quiero recuperar todo lo que herede de la clase Field
.
Pensé que podría recuperarlos aprovechando inspect.getmembers(model)
, pero la lista que devuelve no contiene ninguno de estos campos. Parece que Django ya se ha hecho con la clase y ha agregado todos sus atributos mágicos y ha eliminado lo que realmente se ha definido. Entonces ... ¿cómo puedo obtener estos campos? Probablemente tienen una función para recuperarlos para sus propios fines internos?
El método get_all_related_fields()
mencionado en este documento ha quedado obsoleto en 1.8 . A partir de ahora es get_fields()
.
>> from django.contrib.auth.models import User
>> User._meta.get_fields()
Esto hace el truco. Solo lo pruebo en Django 1.7.
your_fields = YourModel._meta.local_fields
your_field_names = [f.name for f in your_fields]
Model._meta.local_fields
no contiene muchos campos. Debería obtenerlos usando Model._meta.local_many_to_many
.
Me parece muy útil agregar esto a los modelos django:
def __iter__(self):
for field_name in self._meta.get_all_field_names():
value = getattr(self, field_name, None)
yield (field_name, value)
Esto te permite:
for field, val in object:
print field, val
No está claro si tiene una instancia de la clase o la clase en sí e intenta recuperar los campos, pero de cualquier forma, tenga en cuenta el siguiente código
Usando una instancia
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
Usando una clase
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''
Para las versiones 1.8 y posteriores de Django:
El método get_all_field_names()
está en desuso a partir de Django 1.8 y se eliminará en 1.10 .
La página de documentación vinculada anteriormente proporciona una implementación completamente compatible con versiones anteriores de get_all_field_names()
, pero para la mayoría de los propósitos [f.name for f in MyModel._meta.get_fields()]
debería funcionar bien.
Para las versiones de Django anteriores a la 1.8:
model._meta.get_all_field_names()
Eso debería hacer el truco.
Eso requiere una instancia de modelo real. Si todo lo que tiene es una subclase de django.db.models.Model
, debe llamar a myproject.myapp.models.MyModel._meta.get_all_field_names()
Solo para agregar, estoy usando autoobjeto, esto funcionó para mí:
[f.name for f in self.model._meta.get_fields()]
MyModel._meta.get_all_field_names()
se MyModel._meta.get_all_field_names()
varias versiones y se eliminó en Django 1.10.
Aquí está la sugerencia compatible con versiones anteriores de los documentos :
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)
)))
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)
Esto funcionó para mí en django==1.11.8