Django устанавливает DateTimeField для текущего времени сервера
Как сделать эквивалент этого SQL в django?
UPDATE table SET timestamp=NOW() WHERE ...
В частности, я хочу установить поле datetime с помощью встроенной функции сервера, чтобы получить системное время с сервера, на котором работала база данных, а не время на клиентской машине.
Я знаю, что вы можете выполнить raw sql напрямую, но я ищу более портативное решение, поскольку базы данных имеют разные функции для получения текущего времени.
Изменить: несколько человек упомянули параметр auto_now. Это обновляет дату и время при каждой модификации, в то время как я хочу обновлять дату и время только в определенных случаях.
Ответы
Ответ 1
Как сказал j0ker, если вы хотите автоматическое обновление временной метки, используйте параметр auto_now
. Например. date_modified = models.DateTimeField(auto_now=True)
.
Или, если вы хотите сделать это вручную, не просто ли это назначение с помощью python datetime.now()
?
from datetime import datetime
obj.date_modified = datetime.now()
Ответ 2
Принятый ответ устарел. Здесь текущий и самый простой способ сделать это:
from django.utils import timezone
timezone.now()
Ответ 3
Вот как я решил эту проблему. Надеюсь, это сэкономит время:
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)
А затем просто используя DBNow() в качестве значения, в котором требуется обновление и фильтрация:
books = Book.objects.filter(created_on__gt=DBNow())
or:
book.created_on = DBNow()
book.save()
Ответ 4
Вы можете использовать что-то вроде этого, чтобы создать пользовательское значение для представления текущего времени в базе данных:
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
И затем, чтобы иметь возможность использовать DatabaseNow на DateTimeField:
databaseDependentPatch(models.DateTimeField)
Который, в свою очередь, наконец, позволяет вам сделать приятный и чистый:
class Operation(models.Model):
dateTimeCompleted = models.DateTimeField(null=True)
# ...
operation = # Some previous operation
operation.dateTimeCompleted = DatabaseNow()
operation.save()
Ответ 5
Мой измененный код работает с sqlite, mysql и postgresql и немного чище, чем предлагаемые решения.
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)
Я активирую его @в конце моего файла models.py следующим образом:
DBCurrentTimestamp.patch(models.DateField, models.TimeField, models.DateTimeField)
и используйте его следующим образом:
self.last_pageview = DBCurrentTimestamp()
Ответ 6
Я создал модуль плагина Python Django, который позволяет вам управлять использованием объектов CURRENT_TIMESTAMP
on DateTimeField
, как в конкретных случаях (см. ниже usage
), так и автоматически для auto_now
и auto_now_add
.
Джанго-пг-вольт-временная метка
GitHub: https://github.com/jaytaylor/django-pg-current-timestamp
PyPi: https://pypi.python.org/pypi/django-pg-current-timestamp
Пример использования:
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)
Ответ 7
Если вы хотите, чтобы дата-время с иностранного сервера (т.е. не устраивало приложение Django), вам придется привязать его вручную для использования времени использования. Вы могли бы использовать команду SQL, например select now();
или что-то в SSH, например ssh [email protected] "date +%s"
.
Ответ 8
Возможно, вам стоит взглянуть на документацию:
Modelfields: DateField
Параметр "auto_now" может быть только тем, что вы ищете. Вы также можете использовать его с DateTimeField. Он обновляет DateTime каждый раз, когда вы сохраняете модель. Поэтому с этой опцией, установленной для вашего DateTimeField, должно быть достаточно, чтобы получить запись данных и снова сохранить ее, чтобы установить правильное время.