Este dilema se puede solucionar de diferentes formas, pero nosotros te mostramos la que en nuestra opinión es la solución más completa.
class RelatedManager
-
Un “administrador relacionado” es un administrador que se utiliza en un contexto relacionado de uno a muchos o de muchos a muchos. Esto sucede en dos casos:
-
El “otro lado” de un
ForeignKey
relación. Es decir:from django.db import models classBlog(models.Model):# ...passclassEntry(models.Model): blog = models.ForeignKey(Blog, on_delete=models.CASCADE, null=True)
En el ejemplo anterior, los métodos siguientes estarán disponibles en el administrador
blog.entry_set
. -
Ambos lados de un
ManyToManyField
relación:classTopping(models.Model):# ...passclassPizza(models.Model): toppings = models.ManyToManyField(Topping)
En este ejemplo, los métodos siguientes estarán disponibles tanto en
topping.pizza_set
y enpizza.toppings
.
add(*objs, bulk=True, through_defaults=None)
-
Agrega los objetos de modelo especificados al conjunto de objetos relacionados.
Ejemplo:
>>> b = Blog.objects.get(id=1)>>> e = Entry.objects.get(id=234)>>> b.entry_set.add(e)# Associates Entry e with Blog b.
En el ejemplo anterior, en el caso de un
ForeignKey
relación,QuerySet.update()
se utiliza para realizar la actualización. Esto requiere que los objetos ya estén guardados.Puedes usar el
bulk=False
argumento para que el administrador relacionado realice la actualización llamandoe.save()
.Utilizando
add()
con una relación de muchos a muchos, sin embargo, no llamará a ningunasave()
métodos (elbulk
argumento no existe), sino que crea las relaciones utilizandoQuerySet.bulk_create()
. Si necesita ejecutar alguna lógica personalizada cuando se crea una relación, escuche elm2m_changed
señal, que dispararápre_add
ypost_add
comportamiento.Utilizando
add()
en una relación que ya existe no duplicará la relación, pero aún activará señales.Para relaciones de varios a varios
add()
acepta instancias de modelo o valores de campo, normalmente primarios keys, como el*objs
argumento.Utilizar el
through_defaults
argumento para especificar valores para el nuevo modelo intermedio instancia (s), si es necesario. Puede utilizar los callables como valores en elthrough_defaults
diccionario y se evaluarán una vez antes de crear cualquier instancia intermedia.Cambiado en Django 3.1:
through_defaults
los valores ahora pueden ser invocables.
create(through_defaults=None, **kwargs)
-
Crea un nuevo objeto, lo guarda y lo coloca en el conjunto de objetos relacionados. Devuelve el objeto recién creado:
>>> b = Blog.objects.get(id=1)>>> e = b.entry_set.create(... headline='Hello',... body_text='Hi',... pub_date=datetime.date(2005,1,1)...)# No need to call e.save() at this point -- it's already been saved.
Esto es equivalente a (pero más simple que):
>>> b = Blog.objects.get(id=1)>>> e = Entry(... blog=b,... headline='Hello',... body_text='Hi',... pub_date=datetime.date(2005,1,1)...)>>> e.save(force_insert=True)
Tenga en cuenta que no es necesario especificar el argumento de palabra clave del modelo que define la relación. En el ejemplo anterior, no pasamos el parámetro
blog
paracreate()
. Django se da cuenta de que el nuevoEntry
objetosblog
el campo debe establecerse enb
.Utilizar el
through_defaults
argumento para especificar valores para el nuevo modelo intermedio ejemplo, si es necesario. Puede utilizar los callables como valores en elthrough_defaults
diccionario.Cambiado en Django 3.1:
through_defaults
los valores ahora pueden ser invocables.
remove(*objs, bulk=True)
-
Elimina los objetos de modelo especificados del conjunto de objetos relacionados:
>>> b = Blog.objects.get(id=1)>>> e = Entry.objects.get(id=234)>>> b.entry_set.remove(e)# Disassociates Entry e from Blog b.
Similar a
add()
,e.save()
se llama en el ejemplo anterior para realizar la actualización. Utilizandoremove()
con una relación de varios a varios, sin embargo, eliminará las relaciones utilizandoQuerySet.delete()
lo que significa que no hay modelosave()
se llaman métodos; escuchar a lam2m_changed
señal si desea ejecutar código personalizado cuando se elimina una relación.Para relaciones de varios a varios
remove()
acepta instancias de modelo o valores de campo, normalmente primarios keys, como el*objs
argumento.Para
ForeignKey
objetos, este método solo existe sinull=True
. Si el campo relacionado no se puede establecer enNone
(NULL
), entonces un objeto no se puede eliminar de una relación sin agregarse a otro. En el ejemplo anterior, eliminare
deb.entry_set()
es equivalente a hacere.blog = None
, y porque elblog
ForeignKey
no tienenull=True
, esto no es válido.Para
ForeignKey
objetos, este método acepta unbulk
argumento para controlar cómo realizar la operación. SiTrue
(el valor por defecto),QuerySet.update()
se utiliza. Sibulk=False
, lossave()
En su lugar, se llama al método de cada instancia de modelo individual. Esto desencadena elpre_save
ypost_save
señales y se produce a expensas del rendimiento.Para relaciones de muchos a muchos, el
bulk
el argumento de palabra clave no existe.
clear(bulk=True)
-
Elimina todos los objetos del conjunto de objetos relacionados:
>>> b = Blog.objects.get(id=1)>>> b.entry_set.clear()
Tenga en cuenta que esto no elimina los objetos relacionados, solo los disocia.
Al igual que
remove()
,clear()
solo está disponible enForeignKey
s dondenull=True
y también acepta labulk
argumento de palabra clave.Para relaciones de muchos a muchos, el
bulk
el argumento de palabra clave no existe.
set(objs, bulk=True, clear=False, through_defaults=None)
-
Reemplazar el conjunto de objetos relacionados:
>>> new_list =[obj1, obj2, obj3]>>> e.related_set.set(new_list)
Este método acepta un
clear
argumento para controlar cómo realizar la operación. SiFalse
(predeterminado), los elementos que faltan en el nuevo conjunto se eliminan medianteremove()
y solo se agregan los nuevos. Siclear=True
, losclear()
en su lugar, se llama al método y se agrega todo el conjunto a la vez.Para
ForeignKey
objetos, elbulk
el argumento se pasa aadd()
yremove()
.Para relaciones de muchos a muchos, el
bulk
el argumento de palabra clave no existe.Tenga en cuenta que desde
set()
es una operación compuesta, está sujeta a condiciones de carrera. Por ejemplo, se pueden agregar nuevos objetos a la base de datos entre la llamada aclear()
y la llamada aadd()
.Para relaciones de varios a varios
set()
acepta una lista de instancias de modelo o valores de campo, normalmente primario keys, como elobjs
argumento.Utilizar el
through_defaults
argumento para especificar valores para el nuevo modelo intermedio instancia (s), si es necesario. Puede utilizar los callables como valores en elthrough_defaults
diccionario y se evaluarán una vez antes de crear cualquier instancia intermedia.Cambiado en Django 3.1:
through_defaults
los valores ahora pueden ser invocables.
Nota
Tenga en cuenta que
add()
,create()
,remove()
,clear()
, yset()
todos aplican cambios en la base de datos inmediatamente para todos los tipos de campos relacionados. En otras palabras, no es necesario llamarsave()
en cualquier extremo de la relación.Si utiliza
prefetch_related()
, losadd()
,remove()
,clear()
, yset()
Los métodos borran la caché precargada. -