2011-09-24 6 views
10

Me gustaría advertir o evitar que un usuario elimine una instancia de objeto a la que hacen referencia otras instancias. ¿Hay una buena manera de hacer esto?Django: ¿Cómo puedo encontrar cuál de mis modelos se refiere a un modelo?

Una forma sería obtener una lista de modelos que incluyen el referente y luego intentar búsquedas inversas en ellos. ¿Hay alguna manera de obtener esa lista de modelos? ¿O hay un mejor camino?

Mientras investiga la sugerencia colector, me encontré con algo de información relacionada y escribió lo siguiente que encuentra las clases que tienen el referente como una clave externa:

def find_related(cl, app): 
    """Find all classes which are related to the class cl (in app) by 
    having it as a foreign key.""" 

    from django.db import models 

    all_models = models.get_models() 
    ci_model = models.get_model(app, cl) 
    for a_model in all_models: 
     for f in a_model._meta.fields: 
      if isinstance(f, ForeignKey) and (f.rel.to == ci_model): 
       print a_model.__name__ 

Sobre la base de la sugerencia de usar el código de cobro revertido:

def find_related(instance): 
"""Find all objects which are related to instance.""" 

for related in instance._meta.get_all_related_objects(): 
    acc_name = related.get_accessor_name() 
    referers = getattr(instance, acc_name).all() 
    if referers: 
     print related 
+0

Gracias por actualizar esta pregunta con su solución final. Excelente trabajo. – Spike

+0

Tiene 'find_related' tomando' (cl, app) ', mientras' get_model' toma '(app, cl)'. ¡Es realmente confuso! Además, si alguien más está leyendo esto, 'cl' y' app' son cadenas, ¡no pases los objetos! – Casebash

Respuesta

3

Django tiene algo llamado Collector clase. Es utilizado por Django cuando se realiza una eliminación de modelo. Lo que hace parece exactamente lo que quieres. Al llamar al collect(), encuentra todas las referencias al objeto en el gráfico modelo. Además, ofrece una forma de eliminar todos los objetos encontrados, con una llamada delete().

Dicho esto, nunca he usado esta clase, solo sé que existe. La API es un poco intrincada, pero si estás dispuesto a profundizar un poco en el funcionamiento interno de Django, podría ahorrarte mucha codificación.

+0

Eso parece prometedor pero estoy usando 1.0, que solo tiene el antecesor de Collector - CollectedObjects, que no parece tener un método similar. CollectedObjects se usa en (http://stackoverflow.com/questions/437166/duplicating-model-instances-and-the-related-objects-in-django-algorithm-for-r) para encontrar los objetos a los que hace referencia la instancia para ser eliminado – Mitch

+0

¿Podemos suponer que (a) hay una buena razón por la que no puede actualizar a una versión más reciente y (b) del mismo modo, no puede usar el recopilador solo? – Marcin

+0

@Mitch: Sí, estoy de acuerdo con Marcin aquí, que si no puede actualizar, siempre puede intentar usar la implementación 'Collector.collect()' como base para su propio código. El código de Django en general está lejos de ser limpio, pero después de algunos análisis, todavía debe ser utilizable. – julkiewicz

Cuestiones relacionadas