2011-02-08 20 views
7

Estoy tratando de obtener una lista de todos los campos y propiedades de modelos existentes para un objeto determinado. ¿Hay alguna manera de inspeccionar un objeto para que pueda obtener un dict de campos y propiedades?¿Cómo puedo introspectar propiedades y campos modelo en Django?

class MyModel(Model) 
    url = models.TextField() 

    def _get_location(self): 
     return "%s/jobs/%d"%(url, self.id) 

    location = property(_get_location) 

Lo que quiero es algo que devuelve un diccionario que tiene este aspecto:

{ 
    'id' : 1, 
    'url':'http://foo', 
    'location' : 'http://foo/jobs/1' 
} 

puedo usar model._meta.fields para obtener los campos del modelo, pero esto no me da cosas que son propiedades, pero no campos DB reales

Respuesta

8

Si estrictamente desea sólo los campos del modelo y propiedades (las declaradas utilizando la propiedad) entonces:

 
def get_fields_and_properties(model, instance): 
    field_names = [f.name for f in model._meta.fields] 
    property_names = [name for name in dir(model) if isinstance(getattr(model, name), property)] 
    return dict((name, getattr(instance, name) for name in field_names + property_names) 

instance = MyModel() 
print get_fields_and_properties(MyModel, instance) 

La única parte que es adicional aquí se está ejecutando a través de la clasepara encontrar los campos que corresponden a la propiedad descriptores. Acceder a ellos a través de la clase proporciona el descriptor, mientras que a través de la instancia le da los valores.

+0

Gracias - esto es exactamente lo que necesitaba. Estaba tratando de buscar las cosas de tipo "propiedad" dentro de la instancia, pero debería haber estado buscándolas en la clase. – shreddd

0

Debe usar la función dir() en su instancia. Omitir lo que comienza con '__' y luego usar getattr para obtener el valor de tu instancia.

properties = [prop for prop in dir(SomeClass) if not prop.startswith("__")] 

obj = {} 
for prop in properties: 
    obj[prop] = getattr(myinstance, prop) 
+0

No funciona para los modelos Django. Hay muchos otros métodos y variables disponibles para el objeto (heredados de la clase base Django Model) pero no son estrictamente campos o propiedades de Django. Necesito poder distinguir entre propiedades/campos y otras cosas. – shreddd

+0

Para aclarar: me refiero a la función de "propiedad" (http://adam.gomaa.us/blog/2008/aug/11/the-python-property-builtin/) - no solo un atributo genérico de una python objeto. – shreddd

+0

@shreddd: Compare lo que tiene con model._meta.fields para distinguir entre campos y propiedades db. –

1

El problema es que dices que solo quieres campos, pero luego complicas las cosas al arrojar propiedades a la mezcla. Realmente no hay una manera fácil en Python de distinguir entre una propiedad y cualquier otro método aleatorio. Esto no tiene nada que ver con Django: es simplemente que una propiedad es solo un método al que se accede a través de un descriptor. Como cualquier cantidad de elementos de la clase también serán descriptores, tendrá problemas para distinguirlos.

¿Hay alguna razón por la que no puede definir una lista en el nivel de clase que contiene todas las propiedades que desea, luego simplemente llame al getattr en cada uno de los elementos?

0
class Awesome(models.Model): 
foo = models.TextField() 
bar = models.CharField(max_length = 200) 

awe = Awesome() 
for property in awe.__dict__.copy(): 
# pass private properties. 
if not property.startswith('_'): 
    print property,getattr(awe,property) 

Así es como lo hacen en Django.

+1

Esto me da todo dentro del dict, pero no cosas que se declaran usando property(). Parece que necesito ir y sacar esto de la clase Modelo directamente. Vea la solución de John Montgomery arriba. – shreddd

Cuestiones relacionadas