Quero desencadear uma ação especial no método save () de um objeto de modelo do Django quando estou salvando um novo registro (não atualizando um registro existente).
A verificação de (self.id! = None) é necessária e suficiente para garantir que o auto registro seja novo e não esteja sendo atualizado? Algum caso especial que isso possa ignorar?
django
django-models
MikeN
fonte
fonte
UUIDField pk
Respostas:
Atualizado: com o esclarecimento de que
self._state
não é uma variável de instância privada, mas nomeada dessa maneira para evitar conflitos, a verificaçãoself._state.adding
agora é a maneira preferível de verificação.retorna True dentro de um novo objeto Model, a menos que o objeto tenha um
UUIDField
como seuprimary_key
.O caso de canto com o qual você pode se preocupar é se há restrições de exclusividade em outros campos que não o ID (por exemplo, índices exclusivos secundários em outros campos). Nesse caso, você ainda pode ter um novo registro em mãos, mas não poderá salvá-lo.
fonte
is not
em vez de!=
durante a verificação de identidade com oNone
objetomodels.OneToOneField(OtherModel, primary_key=True)
. Eu acho que você precisa usarself.pk
UUIDField
como chave primária,self.pk
nunca éNone
.Maneira alternativa de verificar
self.pk
, podemos verificarself._state
o modeloself._state.adding is True
criandoself._state.adding is False
atualizandoComprei nesta página
fonte
self._state.adding
funciona, mas um aviso justo de que parece sempre igualFalse
se você estiver verificando depois de ligarsuper(TheModel, self).save(*args, **kwargs)
: github.com/django/django/blob/stable/1.10.x/django/db/models/ ..._state
não é privado; como_meta
, é prefixado com um sublinhado para evitar confusão com os nomes dos campos. (Observe como é usado na documentação vinculada.)is_new = self._state.adding
, em seguida,super(MyModel, self).save(*args, **kwargs)
e depoisif is_new: my_custom_logic()
A verificação
self.id
assume que essaid
é a chave principal do modelo. Uma maneira mais genérica seria usar o atalho pk .is_new = self.pk is None
fonte
super(...).save()
.A verificação não
self.pk == None
é suficiente para determinar se o objeto será inserido ou atualizado no banco de dados.O Django O / RM apresenta um hack especialmente desagradável, que é basicamente verificar se há algo na posição PK e, se for o caso, fazer um UPDATE, caso contrário, faça um INSERT (isso é otimizado para um INSERT se o PK for Nenhum).
A razão pela qual isso deve ser feito é porque você tem permissão para definir a PK quando um objeto é criado. Embora não seja comum quando você tem uma coluna de sequência para a chave primária, isso não vale para outros tipos de campos de chave primária.
Se você realmente quer saber, precisa fazer o que o O / RM faz e procurar no banco de dados.
Claro que você tem um caso específico em seu código e, para isso, é bastante provável que
self.pk == None
você tudo o que você precisa saber diz, mas é não uma solução geral.fonte
UUIDField
como chave primária: a chave não é preenchida no nível do banco de dados,self.pk
como sempreTrue
.Você pode simplesmente conectar-se ao sinal post_save que envia um kwargs "criado", se verdadeiro, seu objeto foi inserido.
http://docs.djangoproject.com/en/stable/ref/signals/#post-save
fonte
ATOMIC_REQUESTS
, então não tenho muita certeza sobre o padrão.Verifique
self.id
e aforce_insert
bandeira.Isso é útil porque o seu objeto recém-criado (auto) tem
pk
valorfonte
Estou muito atrasado para esta conversa, mas tive um problema com o self.pk sendo preenchido quando ele tem um valor padrão associado.
A maneira como resolvi isso foi adicionar um campo date_created ao modelo
date_created = models.DateTimeField(auto_now_add=True)
Daqui você pode ir
created = self.date_created is None
fonte
Para uma solução que também funcione mesmo quando você tem uma
UUIDField
chave primária (o que, como outros observaram, não éNone
se você acabou de substituirsave
), você pode conectar o sinal post_save do Django . Adicione isso ao seu models.py :Esse retorno de chamada bloqueará o
save
método, para que você possa executar ações como notificações de gatilho ou atualizar ainda mais o modelo antes que sua resposta seja enviada novamente, seja usando formulários ou a estrutura REST do Django para chamadas AJAX. Obviamente, use responsavelmente e descarregue tarefas pesadas em uma fila de tarefas, em vez de manter os usuários esperando :)fonte
em vez disso, use pk em vez de id :
fonte
É a maneira comum de fazer isso.
o id será dado enquanto salvo pela primeira vez no banco de dados
fonte
Isso funcionaria para todos os cenários acima?
fonte
fonte
Para saber se você está atualizando ou inserindo o objeto (dados), use
self.instance.fieldname
em seu formulário. Defina uma função limpa no seu formulário e verifique se a entrada de valor atual é igual à anterior, caso contrário, você está atualizando.self.instance
eself.instance.fieldname
compare com o novo valorfonte