Подтвердить что ты не робот

Django устанавливает DateTimeField для текущего времени сервера

Как сделать эквивалент этого SQL в django?

UPDATE table SET timestamp=NOW() WHERE ...

В частности, я хочу установить поле datetime с помощью встроенной функции сервера, чтобы получить системное время с сервера, на котором работала база данных, а не время на клиентской машине.

Я знаю, что вы можете выполнить raw sql напрямую, но я ищу более портативное решение, поскольку базы данных имеют разные функции для получения текущего времени.

Изменить: несколько человек упомянули параметр auto_now. Это обновляет дату и время при каждой модификации, в то время как я хочу обновлять дату и время только в определенных случаях.

4b9b3361

Ответ 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, должно быть достаточно, чтобы получить запись данных и снова сохранить ее, чтобы установить правильное время.