tutorial examples python django django-models merge

python - examples - Obtener todos los objetos relacionados con el modelo de Django



django templates examples (9)

¿Cómo puedo obtener una lista de todos los objetos modelo que tienen un ForeignKey apuntando a un objeto? (Algo así como la página de confirmación de eliminación en el administrador de Django antes de BORRAR CASCADA).

Estoy tratando de encontrar una forma genérica de fusionar objetos duplicados en la base de datos. Básicamente quiero que todos los objetos que tienen puntos ForeignKeys para objetar "B" se actualicen para apuntar al objeto "A" para que pueda eliminar "B" sin perder nada importante.

¡Gracias por tu ayuda!


Django <= 1.7

Esto le da los nombres de propiedad para todos los objetos relacionados:

links = [rel.get_accessor_name() for rel in a._meta.get_all_related_objects()]

A continuación, puede utilizar algo como esto para obtener todos los objetos relacionados:

for link in links: objects = getattr(a, link).all() for object in objects: # do something with related object instance

Pasé un tiempo tratando de resolver esto para poder implementar una especie de "Patrón observador" en uno de mis modelos. Espero que sea útil.

Django 1.8+

Utilice _meta.get_fields() : https://docs.djangoproject.com/en/1.10/ref/models/meta/#django.db.models.options.Options.get_fields (consulte también el reverso en la fuente _get_fields() )


@digitalPBK estuvo cerca ... aquí es probablemente lo que estás buscando usando las cosas integradas de Django

from django.db.models.deletion import Collector from django.contrib.admin.util import NestedObjects collector = NestedObjects(using="default") #database name collector.collect([objective]) #list of objects. single one won''t do print collector.data

esto le permite crear lo que muestra el administrador de django: los objetos relacionados que se eliminarán.


Aquí hay otra forma de obtener una lista de campos (solo nombres) en modelos relacionados.

def get_related_model_fields(model): fields=[] related_models = model._meta.get_all_related_objects() for r in related_models: fields.extend(r.opts.get_all_field_names()) return fields


Dale una oportunidad.

class A(models.Model): def get_foreign_fields(self): return [getattr(self, f.name) for f in self._meta.fields if type(f) == models.fields.related.ForeignKey]


Desafortunadamente, user._meta.get_fields () devuelve solo las relaciones accesibles desde el usuario, sin embargo, puede tener algún objeto relacionado, que use related_name = ''+''. En tal caso, la relación no sería devuelta por user._meta.get_fields (). Por lo tanto, si necesita una forma genérica y sólida para fusionar objetos, le sugiero usar el recopilador mencionado anteriormente.


Lo siguiente es lo que django usa para obtener todos los objetos relacionados

from django.db.models.deletion import Collector collector = Collector(using="default") collector.collect([a]) print collector.data


links = [rel.get_accessor_name () for rel in a._meta.get_all_related_objects ()] Luego puede usar algo como esto para obtener todos los objetos relacionados:

para enlace en enlaces: objects = getattr (a, link.name) .all () para objeto en objetos: # hacer algo con instancia de objeto relacionado

De Django 1.10 documentos oficiales:

MyModel._meta.get_all_related_objects () se convierte en:

[ f for f in MyModel._meta.get_fields() if (f.one_to_many or f.one_to_one) and f.auto_created and not f.concrete ]

Entonces, tomando el ejemplo aprobado, usaríamos:

links = [f for f in MyModel._meta.get_fields() if (f.one_to_many or f.one_to_one) and f.auto_created and not f.concrete ] for link in links: objects = getattr(a, link.name).all() for object in objects: # do something with related object instance


Django 1.9
get_all_related_objects () ha quedado obsoleto

#Example: user = User.objects.get(id=1) print(user._meta.get_fields())

Nota: RemovedInDjango110Advertencia: ''get_all_related_objects es una API no oficial que ha sido desaprobada. Puede reemplazarlo con ''get_fields ()''


for link in links: objects = getattr(a, link).all()

Funciona para conjuntos relacionados, pero no para ForeignKeys. Como los Administradores relacionados se crean dinámicamente, mirar el nombre de clase es más fácil que hacer una instancia de instancia ()

objOrMgr = getattr(a, link) if objOrMgr.__class__.__name__ == ''RelatedManager'': objects = objOrMgr.all() else: objects = [ objOrMgr ] for object in objects: # Do Stuff