Python django将DateTimeField设置为服务器的当前时间

Python django将DateTimeField设置为服务器的当前时间,python,database,django,Python,Database,Django,如何在django中实现此SQL的等效功能 UPDATE table SET timestamp=NOW() WHERE ... 特别是我想使用服务器的内置函数设置datetime字段,以从运行数据库的服务器获取系统时间,而不是从客户机获取时间 我知道您可以直接执行原始sql,但我正在寻找一种更具可移植性的解决方案,因为数据库具有获取当前日期时间的不同功能 编辑:很少有人提到auto_now param。这会在每次修改时更新datetime,而我只想在某些情况下更新datetime 也许您应该

如何在django中实现此SQL的等效功能

UPDATE table SET timestamp=NOW() WHERE ...
特别是我想使用服务器的内置函数设置datetime字段,以从运行数据库的服务器获取系统时间,而不是从客户机获取时间

我知道您可以直接执行原始sql,但我正在寻找一种更具可移植性的解决方案,因为数据库具有获取当前日期时间的不同功能


编辑:很少有人提到auto_now param。这会在每次修改时更新datetime,而我只想在某些情况下更新datetime

也许您应该查看一下文档:


选项“auto_now”可能正是您要搜索的内容。您还可以将其与DateTimeField一起使用。每次保存模型时,它都会更新日期时间。因此,为DateTimeField设置该选项后,检索数据记录并再次保存以设置正确的时间就足够了。

正如j0ker所说,如果您希望自动更新时间戳,请使用auto_now选项。例如,date_modified=模型。DateTimeFieldDauto_now=真

或者,如果您想手动执行此操作,它不是一个简单的python datetime.now赋值吗


如果您希望从外部服务器(即,不是托管Django应用程序的服务器)获取datetime,则必须手动将其固定,以便使用datatime。您可以使用类似select now的SQL命令;或者SSH上的东西,比如SSHuser@host日期+%s.

您可以使用类似的方法创建自定义值,以表示当前时间在数据库中的使用情况:

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
然后才能在DateTimeField上使用DatabaseNow:

databaseDependentPatch(models.DateTimeField)
然后,这最终会让你做一个漂亮干净的工作:

class Operation(models.Model):
    dateTimeCompleted = models.DateTimeField(null=True)
    # ...

operation = # Some previous operation
operation.dateTimeCompleted = DatabaseNow()
operation.save()

下面是我如何解决这个问题的。希望它能节省某人的时间:

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()

我已经创建了一个PythonDjango插件模块,它允许您控制DateTimeField对象上当前\u时间戳的使用,在特定情况下,请参见下面的用法,以及auto\u now和auto\u now\u add列的自动使用

django pg当前时间戳

GitHub:

PyPi:

用法示例:

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)

我经过调整的代码可以与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()
然后像这样使用它:

DBCurrentTimestamp.patch(models.DateField, models.TimeField, models.DateTimeField)
self.last_pageview = DBCurrentTimestamp()

公认的答案已经过时了。以下是当前最简单的方法:

>>> from django.utils import timezone
>>> timezone.now()
datetime.datetime(2018, 12, 3, 14, 57, 11, 703055, tzinfo=<UTC>)

您可以使用数据库函数启动Django 1.9:

from django.db.models.functions import Now
Model.objects.filter(...).update(timestamp=Now())

创建表时,要在“添加数据后”字段中创建“现在日期”的字段将此代码添加到字段中

class MyModel(models.Model):
  created_at = models.DateTimeField(auto_now_add=True)
  updated_at = models.DateTimeField(auto_now=True)

Auto_现在会在我不想要的每次更新上更新datetime字段。和python的datetime.now将在客户端获取当前的datetime,但这不能保证与服务器上的datetime接近。datetime.now将如何使用客户端的datetime?视图中的所有Python代码都在服务器上执行,因此它当然使用服务器的日期时间。所谓服务器,我指的是托管数据库的机器,而客户端是运行Python/django并从数据库访问数据的机器。这里的用例是当多台客户机访问数据库并更新时间戳时,如果客户端的系统时间没有同步,这有时是不可能的,因为缺乏权限,这将很难确定条目更新的顺序-这就是为什么最好在服务器上使用系统时间,以便时间戳来自同一个时钟。现在我明白了。你应该把它添加到你的原始问题中,因为我不认为你指的是数据库服务器,只是澄清一下,这不是这个问题的正确答案。请进一步查看@tvorog的答案。然后我会推荐jesse的datetime.now-solution。这比问题中提到的直接执行原始更新sql要复杂得多。我的印象是,您希望sql server的时间显示在Django显示的表单上-您只是希望sql server设置自己的时间吗插入/更新期间的时间?我可以知道您的Django版本吗?我在Django 1.6上的项目中使用了这个示例,但它不起作用,因为Django将使用str的返回值而不是as_SQL的返回值来构造SQL。事实证明,对我来说,Django_conversions.update是使其工作的必要条件,这在其他一些答案中是缺失的。我使用的是Django 1.6。这已经过时了。根据文档,这将返回DB服务器的时间,并且似乎与auto_now和其他版本最为一致。这是正确的答案。请注意,现在翻译成PostgreSQL上的语句_timestamp,可能还有其他的,这相当于现在在大多数正常用例中检查文档以了解更多细节。