J'ai un modèle comme celui-ci:
class FooBar(models.Model):
createtime = models.DateTimeField(auto_now_add=True)
lastupdatetime = models.DateTimeField(auto_now=True)
Je souhaite écraser les deux champs de date pour certaines instances de modèle (utilisées lors de la migration des données). La solution actuelle ressemble à ceci:
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
Y a-t-il une meilleure solution?
auto_now(_add)
Réponses:
J'ai récemment rencontré cette situation en testant mon application. J'avais besoin de "forcer" un horodatage expiré. Dans mon cas, j'ai fait l'affaire en utilisant une mise à jour de jeu de requêtes. Comme ça:
la source
update()
comportement est exactement ce dont nous avons besoin.Vous ne pouvez pas vraiment désactiver auto_now / auto_now_add d'une autre manière que vous ne le faites déjà. Si vous avez besoin de flexibilité pour modifier ces valeurs,
auto_now
/auto_now_add
n'est pas le meilleur choix. Il est souvent plus flexible d'utiliserdefault
et / ou de remplacer lasave()
méthode pour effectuer une manipulation juste avant l'enregistrement de l'objet.En utilisant
default
et unesave()
méthode remplacée , une façon de résoudre votre problème serait de définir votre modèle comme ceci:Dans votre code, où vous souhaitez ignorer le changement automatique de dernière mise à jour, utilisez simplement
Si votre objet est enregistré dans l'interface d'administration ou à d'autres endroits, save () sera appelé sans l'argument skip_lastupdatetime, et il se comportera exactement comme avant avec
auto_now
.la source
auto_now_add
utiliser à ladefault
place.datetime.datetime.now
renvoie un datetime naïf. Pour utiliser un datetime tenant compte du fuseau horaire, utilisezfrom django.utils import timezone
etmodels.DateTimeField(default=timezone.now)
consultez docs.djangoproject.com/en/1.9/topics/i18n/timezonescreatetime
champ, vous n'avez pas besoin de remplacersave()
. Il suffit de le remplacerauto_now_add=True
par l'équivalentdefault=timezone.now, editable=False, blank=True
(selon la documentation ). Les deux dernières options garantissent un comportement similaire dans l'administrateur.J'ai utilisé la suggestion faite par le demandeur et créé quelques fonctions. Voici le cas d'utilisation:
Voici la mise en œuvre:
Des fonctions similaires peuvent être créées pour les réactiver.
la source
Clazz._meta.get_field_by_name(field_name)[0]
.Vous pouvez également utiliser le
update_fields
paramètre desave()
et transmettre vosauto_now
champs. Voici un exemple:Voici l'explication tirée de la documentation de Django: https://docs.djangoproject.com/en/stable/ref/models/instances/#specifying-which-fields-to-save
la source
auto_now
etauto_now_add
).J'ai opté pour le gestionnaire de contexte pour la réutilisation.
Utilisez comme ça:
Boom.
la source
Pour ceux qui regardent cela lorsqu'ils écrivent des tests, il existe une bibliothèque python appelée freezegun qui vous permet de simuler l'heure - donc lorsque le
auto_now_add
code s'exécute, il obtient l'heure que vous voulez réellement. Alors:Il peut également être utilisé comme décorateur - voir le lien ci-dessus pour les documents de base.
la source
Vous pouvez remplacer
auto_now_add
sans code spécial.Je suis tombé sur cette question lorsque j'ai essayé de créer un objet avec une date particulière:
où
publication_date = models.DateField(auto_now_add=True)
.Voici donc ce que j'ai fait:
Cela a été remplacé avec succès
auto_now_add
.En tant que solution à plus long terme, la
save
méthode de remplacement est la voie à suivre: https://code.djangoproject.com/ticket/16583la source
J'avais besoin de désactiver auto_now pour un champ DateTime lors d'une migration et j'ai pu le faire.
la source
Je suis en retard à la fête, mais similaire à plusieurs des autres réponses, c'est une solution que j'ai utilisée lors d'une migration de base de données. La différence avec les autres réponses est que cela désactive tous les champs auto_now pour le modèle sous l'hypothèse qu'il n'y a vraiment aucune raison d'avoir plus d'un de ces champs.
Ensuite, pour l'utiliser, vous pouvez simplement faire:
Et il passera par et nuke tous vos champs
auto_now
etauto_now_add
pour toutes les classes de modèle que vous transmettez.la source
Une version un peu plus propre du gestionnaire de contexte de https://stackoverflow.com/a/35943149/1731460
Vous pouvez l'utiliser même avec des usines (usine-garçon)
la source
copie de Django - Models.DateTimeField - Modification dynamique de la valeur auto_now_add
Eh bien, j'ai passé cet après-midi à le découvrir et le premier problème est de savoir comment récupérer l'objet modèle et où dans le code. Je suis en restframework dans serializer.py, par exemple dans le
__init__
sérialiseur, il ne pourrait pas encore avoir le modèle. Maintenant, dans to_internal_value, vous pouvez obtenir la classe de modèle, après avoir récupéré le champ et après avoir modifié les propriétés du champ comme dans cet exemple:la source
J'avais besoin d'une solution qui fonctionnera avec
update_or_create
, je suis arrivé à cette solution basée sur le code @andreaspelme.Le seul changement est que vous pouvez définir le saut en définissant le champ modifié sur
skip
non seulement en passant kwargskip_modified_update
à la méthode save ().Juste
yourmodelobject.modified='skip'
et la mise à jour sera ignorée!la source