¿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.
Stephen
fuente

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")
Bryan Rehbein
fuente
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")
Tobu
fuente
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.

Tushar.PUCSD
fuente
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")
jbondia
fuente
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

wlashell
fuente