Eu tenho um modelo assim:
class FooBar(models.Model):
createtime = models.DateTimeField(auto_now_add=True)
lastupdatetime = models.DateTimeField(auto_now=True)
Eu quero substituir os dois campos de data para algumas instâncias de modelo (usados ao migrar dados). A solução atual é semelhante a esta:
for field in new_entry._meta.local_fields:
if field.name == "lastupdatetime":
field.auto_now = False
elif field.name == "createtime":
field.auto_now_add = False
new_entry.createtime = date
new_entry.lastupdatetime = date
new_entry.save()
for field in new_entry._meta.local_fields:
if field.name == "lastupdatetime":
field.auto_now = True
elif field.name == "createtime":
field.auto_now_add = True
Existe uma solução melhor?
auto_now(_add)
Respostas:
Recentemente, enfrentei essa situação ao testar meu aplicativo. Eu precisava "forçar" um carimbo de data / hora expirado. No meu caso, fiz o truque usando uma atualização do queryset. Como isso:
fonte
update()
comportamento é exatamente o que precisamos.Você não pode realmente desabilitar auto_now / auto_now_add de outra forma que você já faz. Se você precisa de flexibilidade para alterar esses valores,
auto_now
/auto_now_add
não é a melhor escolha. Freqüentemente, é mais flexível usardefault
e / ou substituir osave()
método para fazer a manipulação logo antes do objeto ser salvo.Usando
default
e umsave()
método substituído , uma maneira de resolver seu problema seria definir seu modelo assim:Em seu código, onde você deseja pular a mudança automática de última atualização, basta usar
Se o seu objeto for salvo na interface de administração ou em outros lugares, save () será chamado sem o argumento skip_lastupdatetime e se comportará exatamente como fazia antes com
auto_now
.fonte
auto_now_add
use emdefault
vez disso.datetime.datetime.now
retorna uma data e hora ingênua. Para usar uma data e hora com reconhecimento de fuso horário, usefrom django.utils import timezone
emodels.DateTimeField(default=timezone.now)
consulte docs.djangoproject.com/en/1.9/topics/i18n/timezones/…createtime
campo, não precisa fazer a substituiçãosave()
. Basta substituirauto_now_add=True
pelo equivalentedefault=timezone.now, editable=False, blank=True
(conforme docs ). As duas últimas opções garantem um comportamento semelhante no administrador.Usei a sugestão do autor da pergunta e criei algumas funções. Aqui está o caso de uso:
Esta é a implementação:
Funções semelhantes podem ser criadas para ativá-los novamente.
fonte
Clazz._meta.get_field_by_name(field_name)[0]
.Você também pode usar o
update_fields
parâmetro desave()
e passar seusauto_now
campos. Aqui está um exemplo:Aqui está a explicação da documentação do Django: https://docs.djangoproject.com/en/stable/ref/models/instances/#specifying-which-fields-to-save
fonte
auto_now
eauto_now_add
).Eu escolhi o caminho do gerenciador de contexto para reutilização.
Use assim:
Estrondo.
fonte
Para aqueles que observam isso quando estão escrevendo testes, existe uma biblioteca python chamada freezegun, que permite falsificar o tempo - então, quando o
auto_now_add
código é executado, ele obtém o tempo que você realmente deseja. Assim:Ele também pode ser usado como um decorador - consulte o link acima para obter os documentos básicos.
fonte
Você pode substituir
auto_now_add
sem código especial.Eu me deparei com esta pergunta quando tentei criar um objeto com uma data específica:
Onde
publication_date = models.DateField(auto_now_add=True)
.Então foi isso que eu fiz:
Isto foi substituído com sucesso
auto_now_add
.Como uma solução de longo prazo, o
save
método de substituição é o caminho a seguir: https://code.djangoproject.com/ticket/16583fonte
Eu precisei desabilitar auto_now para um campo DateTime durante uma migração e consegui fazer isso.
fonte
Estou atrasado para a festa, mas semelhante a várias das outras respostas, esta é uma solução que usei durante uma migração de banco de dados. A diferença das outras respostas é que isso desativa todos os campos auto_now para o modelo sob a suposição de que realmente não há razão para ter mais de um desses campos.
Então, para usá-lo, você pode simplesmente fazer:
E vai passar e destruir todos os seus campos
auto_now
eauto_now_add
para todas as classes de modelo que você passar.fonte
Uma versão um pouco mais limpa do gerenciador de contexto de https://stackoverflow.com/a/35943149/1731460
Você pode usá-lo mesmo com fábricas (menino de fábrica)
fonte
cópia do Django - Models.DateTimeField - Alterando dinamicamente o valor auto_now_add
Bem, passei esta tarde descobrindo e o primeiro problema é como buscar objeto de modelo e onde está no código. Estou no restframework no serializer.py, por exemplo no
__init__
do serializer não poderia ter o Model ainda. Agora em to_internal_value você pode obter a classe do modelo, após obter o campo e depois modificar as propriedades do campo como neste exemplo:fonte
Eu precisava de uma solução que funcionasse
update_or_create
, eu vim para essa solução baseada no código @andreaspelme.A única mudança é que Você pode definir o salto definindo o campo modificado para
skip
não apenas passando o kwargskip_modified_update
para o método save ().Apenas
yourmodelobject.modified='skip'
e a atualização será ignorada!fonte