Maneira correta de usar get_or_create?

203

Estou tentando usar get_or_create para alguns campos nos meus formulários, mas estou recebendo um erro 500 quando tento fazer isso.

Uma das linhas é assim:

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

O erro que recebo para o código acima é:

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

Respostas:

353

Na documentação 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

Explicação: Os campos a serem avaliados quanto à similaridade devem ser mencionados fora defaults. O restante dos campos deve ser incluído defaults. Caso o evento CREATE ocorra, todos os campos são levados em consideração.

Parece que você precisa retornar para uma tupla, em vez de uma única variável, faça o seguinte:

customer.source,created = Source.objects.get_or_create(name="Website")
Bryan Rehbein
fonte
3
FYI criado é um booleano. Verdadeiro se criado, False se ele é buscado
Josh
3
Um adicional save()é redundante?
Zypro
@zypro É como create()criar um objeto e salvar tudo em uma única etapa e não precisa de nenhumsave()
Amin Mir
32

get_or_create retorna uma tupla.

customer.source, created = Source.objects.get_or_create(name="Website")
Tobu
fonte
16
Ou, se você não se importa com a bandeira booleana:customer.source = Source.objects.get_or_create(name="Website")[0]
mipadi 21/12/2009
7
@mipadi Eu preferiria customer.source, _ = Source.objects.get_or_create(name="Website"), pois torna o fato de que uma tupla foi retornada mais óbvia, ajudando a evitar futuros erros.
Solomon Ucko
15

get_or_create() retorna uma tupla:

customer.source, created  = Source.objects.get_or_create(name="Website")
  • created tem um valor booleano, é criado ou não.

  • customer.source tem um objeto de get_or_create()método.

Tushar.PUCSD
fonte
12

Seguindo a resposta @Tobu e o comentário @mipadi, de uma maneira mais pitônica, se não estiver interessado na bandeira criada, eu usaria:

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

O problema que você está enfrentando é um recurso documentado get_or_create.

Ao usar argumentos de palavra-chave que não sejam "padrões", o valor de retorno get_or_createé uma instância. É por isso que está mostrando os parênteses no valor de retorno.

você pode usar customer.source = Source.objects.get_or_create(name="Website")[0]para obter o valor correto.

Aqui está um link para a documentação: http://docs.djangoproject.com/en/dev/ref/models/querysets/#get-or-create-kwargs

wlashell
fonte