¿Cómo usar “get_or_create()” en Django?

4 minutos de lectura

Avatar de usuario de Stephen
Esteban

estoy tratando de usar get_or_create() para algunos campos en mis formularios, pero recibo un error 500 cuando intento hacerlo.

Una de las líneas se ve así:

customer.source = Source.objects.get_or_create(name="Website")

El error que obtengo para el código anterior es:

No se puede asignar “(, Falso)”: “Cliente.fuente” debe ser una instancia de “Fuente”.

Avatar de usuario de Astra
Astra

De la documentación obtener_o_crear:

# get_or_create() a person with similar first names.

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

# get_or_create() didn't have to create an object.
>>> created
False

Explicación:
Los campos para evaluar la similitud deben mencionarse fuera defaults. El resto de los campos tienen que ser incluidos en defaults. En caso de que ocurra el evento CREAR, todos los campos se tienen en cuenta.

Parece que necesita volver a una tupla, en lugar de una sola variable, haga lo siguiente:

customer.source,created = Source.objects.get_or_create(name="Website")

  • FYI creado es un booleano. Verdadero si se crea, falso si se obtiene

    – José

    4 de octubre de 2018 a las 8:45

  • un adicional save() es redundante?

    – zypro

    17 de diciembre de 2019 a las 10:56

  • @zypro Es como create()crea un objeto y guárdalo todo en un solo paso y no necesita ningún save()

    – Amin Mir

    19 de junio de 2020 a las 6:05

  • NOTA: A partir de Django 3.2, cualquier declaración pasada en defaults se evalúan incluso si no se crea un nuevo objeto. Terminé escribiendo la instrucción try catch cada vez que create necesita una declaración compleja para ejecutarse.

    – Iqbal

    26 de julio de 2021 a las 17:03


  • ¿Qué significa la p en “p, created = Person…”? ¿Cuál es el propósito?

    – alkadélico

    22 de marzo a las 21:31

Avatar de usuario de Tobu
tobu

get_or_create devuelve una tupla.

customer.source, created = Source.objects.get_or_create(name="Website")

  • O, si no te importa la bandera booleana: customer.source = Source.objects.get_or_create(name="Website")[0]

    – mipadi

    21 de diciembre de 2009 a las 16:57

  • @mipadi yo preferiría customer.source, _ = Source.objects.get_or_create(name="Website")ya que hace más evidente el hecho de que se devolvió una tupla, lo que ayuda a evitar futuros errores.

    – Salomón Ucko

    4 de abril de 2019 a las 2:32

Avatar de usuario de Tushar Patil
Tushar patil

get_or_create() devuelve una tupla:

customer.source, created  = Source.objects.get_or_create(name="Website")
  • created tiene un valor booleano, se crea o no.

  • customer.source tiene un objeto de get_or_create() método.

Siguiendo la respuesta de @Tobu y el comentario de @mipadi, de una manera más pitónica, si no estoy interesado en la bandera creada, usaría:

customer.source, _ = Source.objects.get_or_create(name="Website")

avatar de usuario de wlashell
concha

El problema que está encontrando es una característica documentada de get_or_create.

Cuando se utilizan argumentos de palabras clave que no sean “predeterminados”, el valor de retorno de get_or_create es una instancia. Es por eso que le muestra los paréntesis en el valor de retorno.

podrías usar customer.source = Source.objects.get_or_create(name="Website")[0] para obtener el valor correcto.

Aquí hay un enlace para la documentación:
http://docs.djangoproject.com/en/dev/ref/models/querysets/#get-or-create-kwargs

El método get_or_create en realidad devolvería una tupla.

El truco con el método get_or_create es que en realidad devuelve una tupla de (objeto, creado). El primer elemento es una instancia del modelo que está tratando de recuperar y el segundo es un indicador booleano para indicar si la instancia se creó o no. Verdadero significa que la instancia fue creada por el método get_or_create y Falso significa que fue recuperada de la base de datos

Entonces puedes hacer algo como obtener la instancia de origen

 ```   customer.source = Source.objects.get_or_create(name="Website")[0]
 ```

Super Kai - Avatar de usuario de Kazuya Ito
Súper Kai – Kazuya Ito

obtener_o_crear() devuelve la tupla que contiene 2 valores y el primer valor es un objeto y el segundo valor es el valor booleano que indica que se crea o no un nuevo objeto como se muestra a continuación:

 # 1st   # 2nd
(object, boolean)

Entonces, si quieres ambos un objeto y un valor booleanoponer una variable más created después customer.source Como se muestra abajo:

                 # Here
customer.source, created = Source.objects.get_or_create(name="Website")
# object         # boolean

Y si quieres solo un objeto sin un valor booleano, poner [0] justo después de get_or_create() Como se muestra abajo:

                                                       # Here ↓↓↓
customer.source = Source.objects.get_or_create(name="Website")[0]
# object

Y si quieres solo un valor booleano sin un objeto puesto [1] justo después de get_or_create() Como se muestra abajo:

                                               # Here ↓↓↓
created = Source.objects.get_or_create(name="Website")[1]
# boolean

¿Ha sido útil esta solución?