2010-01-14 23 views
43

Diga my_instance es del modelo MyModel.
Busco una buena manera de hacerlo:django: la mejor forma de obtener el modelo de una instancia de ese modelo

my_model = get_model_for_instance(my_instance) 

no he encontrado ninguna manera muy directa de hacerlo. Hasta aquí he llegado con esto:

from django.db.models import get_model 

my_model = get_model(my_instance._meta.app_label, my_instance.__class__.__name__) 

Es esto aceptable? ¿Es incluso una forma segura de hacer las mejores prácticas para hacerlo?
También hay _meta.object_name que parece entregar lo mismo que __class__.__name__. ¿Lo hace? Es mejor o peor? Si es así, ¿por qué?

Además, ¿cómo sé que estoy obteniendo el modelo correcto si la etiqueta de la aplicación aparece varias veces dentro del alcance del proyecto, por ej. 'auth' de 'django.contrib.auth' y que también haya 'myproject.auth'?
¿Tal caso haría get_model poco confiable?

¡Gracias por cualquier pista/indicación y compartir experiencia!

+3

La '__class__' absolutamente ** debe ** ser la clase para la instancia. No hay ambigüedad posible. Esa es la forma en que funciona Python. ¿Que estas preguntando? –

+0

Bueno, tengo algunos límites de comprensión aquí. Para mí, la ambigüedad es que podría haber más de una combinación de etiqueta de aplicación/nombre de clase, que viven en diferentes módulos. Sin embargo, get_model no recibe el módulo como entrada. Entonces, ¿qué modelo entregará? La otra cosa es que no entiendo para qué object_name es bueno, ya que devuelve la misma cadena que '__class __.__ name__', y cuántas personas eligen cuál de esas dos para el uso en' get_model' o en otro lugar. Gracias! – Geradeausanwalt

Respuesta

69
my_model = type(my_instance) 

para probarlo, puede crear otra instancia:

my_new_instance = type(my_instance)() 

Es por esto que no hay forma directa de hacerlo, ya que los objetos de Python ya tienen esta característica.

actualizado ...

me gusta marcinn's response que utiliza type(x). Esto es idéntico a lo que usó la respuesta original (x.__class__), pero prefiero usar funciones para acceder a attribus mágicos. De esta manera, prefiero usar vars(x) a x.__dict__, len(x) a x.__len__ y así sucesivamente.

actualizado 2 ...

Para los casos diferidos (mencionados por @Cerin en comentarios) se puede acceder a través de la clase original instance._meta.proxy_for_model.

+2

Esto no funciona con instancias diferidas o instancias de consultas que usan 'only()'. – Cerin

19
my_new_instance = type(my_instance)() 
Cuestiones relacionadas