¿Forma correcta de usar get_or_create?


203

Estoy tratando de usar get_or_create para algunos campos en mis formularios, pero obtengo 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:

Cannot assign "(<Source: Website>, False)": "Customer.source" 
   must be a "Source" instance.

Respuestas:


353

De la documentación get_or_create :

# 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 que se evaluarán por similitud deben mencionarse en el exterior defaults. El resto de los campos deben incluirse defaults. En caso de que se produzca el evento CREATE, se tienen en cuenta todos los campos.

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

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

3
FYI creado es un booleano. Es cierto que si se crea, False si es inverosímil
Josh

3
¿Un adicional save()es redundante?
zypro

@zypro Es como create()crear un objeto y guardarlo todo en un solo paso y no necesita ningunosave()
Amin Mir

32

get_or_create devuelve una tupla

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

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

77
@mipadi Preferiría customer.source, _ = Source.objects.get_or_create(name="Website"), ya que hace que el hecho de que se devuelva una tupla sea más obvio, lo que ayuda a evitar futuros errores.
Solomon Ucko

15

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.


12

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")

4

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

Cuando se utilizan argumentos de palabras clave distintos de "valores predeterminados", el valor de retorno de get_or_createes una instancia. Es por eso que le muestra los parens en el valor de retorno.

podría 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

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.