Comment puis-je faire l'équivalent de ce SQL dans django?
UPDATE table SET timestamp=NOW() WHERE ...
En particulier, je souhaite définir le champ datetime à l'aide de la fonction intégrée du serveur pour obtenir l'heure système du serveur sur lequel la base de données s'exécutait et non l'heure sur la machine cliente.
Je sais que vous pouvez exécuter le SQL brut directement, mais je recherche une solution plus portable car les bases de données ont différentes fonctions pour obtenir l'heure actuelle.
Edit: peu de gens ont mentionné le paramètre auto_now. Cela met à jour le datetime à chaque modification alors que je ne veux mettre à jour le datetime qu'à certaines occasions.
Comme l'a dit j0ker, si vous voulez une mise à jour automatique de l'horodatage, utilisez l'option auto_now
. Par exemple. date_modified = models.DateTimeField(auto_now=True)
.
Ou si vous voulez le faire manuellement, n'est-ce pas une simple affectation avec python datetime.now()
?
from datetime import datetime
obj.date_modified = datetime.now()
La réponse acceptée est obsolète. Voici la manière actuelle et la plus simple de le faire:
>>> from Django.utils import timezone
>>> timezone.now()
datetime.datetime(2018, 12, 3, 14, 57, 11, 703055, tzinfo=<UTC>)
Voici comment j'ai résolu ce problème. J'espère que cela fait gagner du temps à quelqu'un:
from Django.db import models
class DBNow(object):
def __str__(self):
return 'DATABASE NOW()'
def as_sql(self, qn, val):
return 'NOW()', {}
@classmethod
def patch(cls, field):
orig_prep_db = field.get_db_prep_value
orig_prep_lookup = field.get_prep_lookup
orig_db_prep_lookup = field.get_db_prep_lookup
def prep_db_value(self, value, connection, prepared=False):
return value if isinstance(value, cls) else orig_prep_db(self, value, connection, prepared)
def prep_lookup(self, lookup_type, value):
return value if isinstance(value, cls) else orig_prep_lookup(self, lookup_type, value)
def prep_db_lookup(self, lookup_type, value, connection, prepared=True):
return value if isinstance(value, cls) else orig_db_prep_lookup(self, lookup_type, value, connection=connection, prepared=True)
field.get_db_prep_value = prep_db_value
field.get_prep_lookup = prep_lookup
field.get_db_prep_lookup = prep_db_lookup
# DBNow Activator
DBNow.patch(models.DateTimeField)
Et puis juste en utilisant le DBNow () comme une valeur où la mise à jour et le filtrage sont nécessaires:
books = Book.objects.filter(created_on__gt=DBNow())
or:
book.created_on = DBNow()
book.save()
Vous pouvez utiliser la fonction de base de données Maintenant démarrage Django 1.9:
from Django.db.models.functions import Now
Model.objects.filter(...).update(timestamp=Now())
Vous pouvez utiliser quelque chose comme ceci pour créer une valeur personnalisée pour représenter l'utilisation de l'heure actuelle dans la base de données:
class DatabaseDependentValue(object):
def setEngine(self, engine):
self.engine = engine
@staticmethod
def Converter(value, *args, **kwargs):
return str(value)
class DatabaseNow(DatabaseDependentValue):
def __str__(self):
if self.engine == 'Django.db.backends.mysql':
return 'NOW()'
Elif self.engine == 'Django.db.backends.postgresql':
return 'current_timestamp'
else:
raise Exception('Unimplemented for engine ' + self.engine)
Django_conversions.update({DatabaseNow: DatabaseDependentValue.Converter})
def databaseDependentPatch(cls):
originalGetDbPrepValue = cls.get_db_prep_value
def patchedGetDbPrepValue(self, value, connection, prepared=False):
if isinstance(value, DatabaseDependentValue):
value.setEngine(connection.settings_dict['ENGINE'])
return value
return originalGetDbPrepValue(self, value, connection, prepared)
cls.get_db_prep_value = patchedGetDbPrepValue
Et puis pour pouvoir utiliser DatabaseNow sur un DateTimeField:
databaseDependentPatch(models.DateTimeField)
Ce qui à son tour vous permet enfin de faire un Nice and clean:
class Operation(models.Model):
dateTimeCompleted = models.DateTimeField(null=True)
# ...
operation = # Some previous operation
operation.dateTimeCompleted = DatabaseNow()
operation.save()
Mon code modifié fonctionne avec sqlite, mysql et postgresql et est un peu plus propre que les solutions proposées.
class DBCurrentTimestamp:
def __str__(self):
return 'DATABASE CURRENT_TIMESTAMP()'
def as_sql(self, qn, connection):
return 'CURRENT_TIMESTAMP', {}
@classmethod
def patch(cls, *args):
def create_tweaked_get_db_prep_value(orig_get_db_prep_value):
def get_db_prep_value(self, value, connection, prepared=False):
return value if isinstance(value, cls) else orig_get_db_prep_value(self, value, connection, prepared)
return get_db_prep_value
for field_class in args:
field_class.get_db_prep_value = create_tweaked_get_db_prep_value(field_class.get_db_prep_value)
Je l'active à la fin de mon fichier models.py comme ceci:
DBCurrentTimestamp.patch(models.DateField, models.TimeField, models.DateTimeField)
et utilisez-le comme ceci:
self.last_pageview = DBCurrentTimestamp()
J'ai créé un Python Django qui vous permet de contrôler l'utilisation de CURRENT_TIMESTAMP
sur DateTimeField
objets, à la fois dans des cas spécifiques (voir usage
ci-dessous) ainsi que automatiquement pour auto_now
et auto_now_add
colonnes.
Django-pg-current-timestamp
GitHub: https://github.com/jaytaylor/Django-pg-current-timestamp
PyPi: https://pypi.python.org/pypi/Django-pg-current-timestamp
Exemple d'utilisation:
from Django_pg_current_timestamp import CurrentTimestamp
mm = MyModel.objects.get(id=1)
mm.last_seen_date = CurrentTimestamp()
mm.save()
## Resulting SQL:
## UPDATE "my_model" SET "last_seen_date" = CURRENT_TIMESTAMP;
print MyModel.objects.filter(last_seen_date__lt=CURRENT_TIME).count()
MyModel.objects.filter(id__in=[1, 2, 3]).update(last_seen_date=CURRENT_TIME)
Si vous voulez que le datetime à partir d'un serveur étranger (c'est-à-dire pas celui qui héberge l'application Django), vous devrez le rattacher manuellement pour un datatime à utiliser. Vous pouvez utiliser un Commande SQL comme select now();
ou quelque chose sur SSH, comme ssh user@Host "date +%s"
.
Vous devriez peut-être jeter un œil à la documentation:
Modelfields: DateField
L'option 'auto_now' pourrait être exactement ce que vous recherchez. Vous pouvez également l'utiliser avec DateTimeField. Il met à jour le DateTime chaque fois que vous enregistrez le modèle. Donc, avec cette option définie pour votre DateTimeField, il devrait être suffisant de récupérer un enregistrement de données et de le sauvegarder à nouveau pour régler l'heure correctement.