Tengo un modelo que representa a un propietario. Hay una clave externa en este modelo para representar a una entidad matriz. Hay otro modelo llamado activo con clave externa al propietario. El propósito de la clave externa principal es emular una estructura corporativa, de modo que una matriz "posee" un Activo cuya clave externa es ella misma o una subsidiaria:
Class Owner(models.Model): parent = models.ForeignKey( “self”, ) Class Asset(models.Model): owner = models.ForeignKey( Owner, )¿Hay alguna manera de devolver todos los activos propiedad de una matriz y todas sus subsidiarias simplemente haciendo referencia a la matriz (p. ej., Asset.object.filter(owner=parent))? Sé que puedo crear un método para devolver un conjunto de consultas de todas las subsidiarias de un padre y luego filtrar a todos los activos en ese conjunto de consultas propietario, pero espero evitar una refactorización grande dado que la base de código existente no tiene el concepto de un padre propietario.
Mi primer pensamiento es un administrador personalizado, pero no creo que eso cambie el comportamiento de las consultas existentes que están todas fuera del administrador predeterminado. ¿Puedo sobrecargar el filtro en este modelo? Si necesito repensar el diseño, está bien, pero creo que este enfoque es más limpio y captura el comportamiento que queremos. ¡Gracias!
Posiblemente no sea una respuesta satisfactoria o completa, pero tengo una consulta de postgres sin procesar que devuelve todos los elementos secundarios de un padre en una sola consulta. Utiliza una consulta recursiva .
class Owner(models.Model): parent = models.ForeignKey('self', on_delete=models.SET_NULL, null=True, blank=True) def get_all_children(self): return Owner.objects.raw(f""" with recursive t(id, parent_id) as ( select id, parent_id from app_owner where id={self.id} union all select b.id, b.parent_id from app_owner b join t on b.parent_id=t.id ) select * from t """)Esto también se puede usar para filtrar activos
Asset.objects.filter(owner__in=Owner.objects.get(id=1).get_all_children())