Crear si no existe

81

Tengo una aplicación Django que lee datos de una API web y los coloca en una base de datos.
¿Hay alguna forma de crear un nuevo objeto a partir de un modo pero evitar la excepción duplicada si el objeto ya existe?

En otras palabras, ¿hay alguna forma de guardar un objeto, pero no hacer nada si ya existe?

usuario1094786
fuente

Respuestas:

161

Model.objects.get_or_create()

segundo
fuente
9
convertirlo en un enlace a los documentos agrega algunos caracteres (y lo convierte en una mejor respuesta, supongo)
segundo
4
Esto parece hacer 2 consultas. Si solo quiero guardar el objeto en caso de que no exista, ¿hay alguna forma con solo 1 consulta? Supongo que la captura IntegrityErrorhace que la transacción actual se anule y no es suficiente.
Amir Ali Akbari
puede detectar el error de integridad si agrega un punto de guardado, por ejemplo, utilizando transaction.atomic(asegúrese de detectar fuera del atomicbloque, es decir try: with acomic: create; except IntegrityError, también es complicado asegurarse de no detectar otros errores de integridad que no sea el que pretende
segundo
Si puede detectar el IntegrityError, mis pruebas muestran que reduce el tiempo de ejecución casi a la mitad cuando existe el registro en comparación con get_or_create().
Ron
3

Parece que en las versiones más recientes de Django, la función save () realiza una ACTUALIZACIÓN o INSERT de forma predeterminada. Vea aquí .

crperez
fuente
parece que debería elegir bien automáticamente, sin embargo, en mi base de datos actualmente está duplicando entradas cada vez que ejecuto mi script para completar la base de datos.
martin-martin
el método save () comprueba si el PK del modelo tiene un valor. El autor tendría que consultar la base de datos para obtener la instancia del modelo con el PK correcto para utilizar esta técnica. El solo uso de save () no hace la magia.
chickahoona
0

Se puede lograr usando Model.objects.get_or_create()

Ejemplo

obj, created = Person.objects.get_or_create(
    first_name='John',
    last_name='Lennon',
    defaults={'birthday': date(1940, 10, 9)},
)

Cualquier argumento de palabra clave (aquí first_name y last_name ) pasado a get_or_create () - excepto uno opcional llamado defaults - se usará para consultar en la base de datos (encontrar el objeto) en la base de datos.

Devuelve una tupla, si se encuentra un objeto, get_or_create () devuelve una tupla de ese objeto y False.

Nota : Lo mismo también se puede lograr usando try exceptdeclaraciones
Ejemplo:

try:
    obj = Person.objects.get(first_name='John', last_name='Lennon')
except Person.DoesNotExist:
    obj = Person(first_name='John', last_name='Lennon', birthday=date(1940, 10, 9))
    obj.save()
Abhishek Pratap Singh
fuente