django устанавливает DateTimeField на текущее время сервера - PullRequest
42 голосов
/ 19 сентября 2011

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

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

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

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

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

Ответы [ 9 ]

52 голосов
/ 19 сентября 2011

Как сказал j0ker, если вы хотите автоматическое обновление отметки времени, используйте опцию auto_now.Например, date_modified = models.DateTimeField(auto_now=True).

Или, если вы хотите сделать это вручную, разве это не простое задание с python datetime.now()?

from datetime import datetime

obj.date_modified = datetime.now()
28 голосов
/ 01 февраля 2017

Принятый ответ устарел. Вот текущий и самый простой способ сделать это:

>>> from django.utils import timezone
>>> timezone.now()
datetime.datetime(2018, 12, 3, 14, 57, 11, 703055, tzinfo=<UTC>)
8 голосов
/ 10 августа 2013

Вот как я решил эту проблему.Надеюсь, это сэкономит кому-то время:

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()
7 голосов
/ 29 января 2018

Вы можете использовать функцию базы данных Сейчас , начиная с Django 1.9:

from django.db.models.functions import Now
Model.objects.filter(...).update(timestamp=Now())
5 голосов
/ 19 апреля 2012

Вы можете использовать что-то вроде этого, чтобы создать пользовательское значение для представления использования текущего времени в базе данных:

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()
4 голосов
/ 05 января 2015

Мой измененный код работает с 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()
3 голосов
/ 10 сентября 2014

Я создал модуль плагина Python Django, который позволяет вам контролировать использование CURRENT_TIMESTAMP на DateTimeField объектах, как в особых случаях (см. usage ниже), так и автоматически для auto_now и auto_now_add столбцы.

django-pg-current-timestamp

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)
2 голосов
/ 19 сентября 2011

Если вы хотите использовать дату и время на внешнем сервере (т.е. не на том, на котором размещено приложение Django), вам придется привязать его вручную для использования времени данных. Вы можете использовать команду SQL, например select now(); или что-то поверх SSH, например ssh user@host "date +%s".

1 голос
/ 19 сентября 2011

Может быть, вам стоит взглянуть на документацию:
Поля модели: DateField

Опция 'auto_now' может быть именно тем, что вы ищете. Вы также можете использовать его с DateTimeField. Он обновляет DateTime каждый раз, когда вы сохраняете модель. Таким образом, с этой опцией, установленной для вашего DateTimeField, должно быть достаточно извлечь запись данных и сохранить ее снова, чтобы установить правильное время.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...