超过5小时的对象的 Django 查询日期时间

我正在尝试编写一个 Django 查询的小部件是超过5小时,我有点迷路了。小部件模型有一个用小部件的创建时间填充的 DateTimeField

72819 次浏览

如果 Widget是您的模型的名称,并且它有一个名为 created的 DateTimeField 属性,那么查询将是:

from datetime import datetime, timedelta


time_threshold = datetime.now() - timedelta(hours=5)
results = Widget.objects.filter(created__lt=time_threshold)

请注意,created__lt的意思是“创建小于”。

now = datetime.datetime.now()
earlier = now - datetime.timedelta(hours=5)
MyModel.objects.filter(my_date_field__range=(earlier,now))

这样应该可以了。

如果 setings.USE _ TZ = True 和 setings.TIME _ ZONE 正在设置

from django.utils import timezone
five_h_ago = timezone.now()-timezone.timedelta(hours=5)
example.object.filter(datetimefield__lt=five_h_ago)

其他答案已经涵盖了最简单的方法: 只需筛选日期早于5小时的记录。下面是一个完整的示例,它可以查找至少5秒钟前创建的记录:

# Tested with Django 1.11.15 and Python 3.6.
import logging
import sys
from datetime import datetime, timedelta
from time import sleep


import django
from django.apps import apps
from django.apps.config import AppConfig
from django.conf import settings
from django.db import connections, models, DEFAULT_DB_ALIAS
from django.db.models.base import ModelBase


NAME = 'udjango'
DB_FILE = NAME + '.db'




def main():
setup()
logger = logging.getLogger(__name__)


class Widget(models.Model):
name = models.CharField(max_length=200)
date_created = models.DateTimeField(auto_now_add=True)


def __str__(self):
return self.name


syncdb(Widget)


Widget.objects.create(name='spline')
sleep(1)
Widget.objects.create(name='reticulator')
sleep(1)
Widget.objects.create(name='tardis')
sleep(5)
Widget.objects.create(name='sonic screwdriver')
sleep(1)


cutoff_time = datetime.now() - timedelta(seconds=5)
for widget in Widget.objects.filter(date_created__lt=cutoff_time):
logger.info(widget.name)




def setup():
with open(DB_FILE, 'w'):
pass  # wipe the database
settings.configure(
DEBUG=True,
DATABASES={
DEFAULT_DB_ALIAS: {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': DB_FILE}},
LOGGING={'version': 1,
'disable_existing_loggers': False,
'formatters': {
'debug': {
'format': '[%(levelname)s]'
'%(name)s.%(funcName)s(): %(message)s',
'datefmt': '%Y-%m-%d %H:%M:%S'}},
'handlers': {
'console': {
'level': 'DEBUG',
'class': 'logging.StreamHandler',
'formatter': 'debug'}},
'root': {
'handlers': ['console'],
'level': 'INFO'},
'loggers': {
"django.db": {"level": "INFO"}}})
app_config = AppConfig(NAME, sys.modules['__main__'])
apps.populate([app_config])
django.setup()
original_new_func = ModelBase.__new__


@staticmethod
def patched_new(cls, name, bases, attrs):
if 'Meta' not in attrs:
class Meta:
app_label = NAME
attrs['Meta'] = Meta
return original_new_func(cls, name, bases, attrs)
ModelBase.__new__ = patched_new




def syncdb(model):
""" Standard syncdb expects models to be in reliable locations.


Based on https://github.com/django/django/blob/1.9.3
/django/core/management/commands/migrate.py#L285
"""
connection = connections[DEFAULT_DB_ALIAS]
with connection.schema_editor() as editor:
editor.create_model(model)




main()

除了最后一个小部件之外,我看到了所有的东西:

[INFO]__main__.main(): spline
[INFO]__main__.main(): reticulator
[INFO]__main__.main(): tardis

除非您启用了时区支持,否则这样可以很好地工作。在前面的示例中,我通过将 settings.configure(...更改为如下所示来实现这一点:

settings.configure(
USE_TZ=True,
...

当我这样做的时候,我会得到这样的信息:

RuntimeWarning: DateTimeField Widget.date_created received a naive datetime (2019-01-07 16:39:04.563563) while time zone support is active.

要获得时区感知日期,请使用 timezone.now()功能而不是 datetime.now():

# Tested with Django 1.11.15 and Python 3.6.
import logging
import sys
from datetime import timedelta
from time import sleep


import django
from django.apps import apps
from django.apps.config import AppConfig
from django.conf import settings
from django.db import connections, models, DEFAULT_DB_ALIAS
from django.db.models.base import ModelBase
from django.utils import timezone


NAME = 'udjango'
DB_FILE = NAME + '.db'




def main():
setup()
logger = logging.getLogger(__name__)


class Widget(models.Model):
name = models.CharField(max_length=200)
date_created = models.DateTimeField(auto_now_add=True)


def __str__(self):
return self.name


syncdb(Widget)


Widget.objects.create(name='spline')
sleep(1)
Widget.objects.create(name='reticulator')
sleep(1)
Widget.objects.create(name='tardis')
sleep(5)
Widget.objects.create(name='sonic screwdriver')
sleep(1)


cutoff_time = timezone.now() - timedelta(seconds=5)
for widget in Widget.objects.filter(date_created__lt=cutoff_time):
logger.info(widget.name)




def setup():
with open(DB_FILE, 'w'):
pass  # wipe the database
settings.configure(
USE_TZ=True,
DEBUG=True,
DATABASES={
DEFAULT_DB_ALIAS: {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': DB_FILE}},
LOGGING={'version': 1,
'disable_existing_loggers': False,
'formatters': {
'debug': {
'format': '[%(levelname)s]'
'%(name)s.%(funcName)s(): %(message)s',
'datefmt': '%Y-%m-%d %H:%M:%S'}},
'handlers': {
'console': {
'level': 'DEBUG',
'class': 'logging.StreamHandler',
'formatter': 'debug'}},
'root': {
'handlers': ['console'],
'level': 'INFO'},
'loggers': {
"django.db": {"level": "INFO"}}})
app_config = AppConfig(NAME, sys.modules['__main__'])
apps.populate([app_config])
django.setup()
original_new_func = ModelBase.__new__


@staticmethod
def patched_new(cls, name, bases, attrs):
if 'Meta' not in attrs:
class Meta:
app_label = NAME
attrs['Meta'] = Meta
return original_new_func(cls, name, bases, attrs)
ModelBase.__new__ = patched_new




def syncdb(model):
""" Standard syncdb expects models to be in reliable locations.


Based on https://github.com/django/django/blob/1.9.3
/django/core/management/commands/migrate.py#L285
"""
connection = connections[DEFAULT_DB_ALIAS]
with connection.schema_editor() as editor:
editor.create_model(model)




main()

有时,我会遇到数据库时钟与网络服务器时钟不同步的问题。为了避免这种问题,可以使用 Now()功能获取数据库中的当前时间。

# Tested with Django 1.11.15 and Python 3.6.
import logging
import sys
from datetime import timedelta
from time import sleep


import django
from django.apps import apps
from django.apps.config import AppConfig
from django.conf import settings
from django.db import connections, models, DEFAULT_DB_ALIAS
from django.db.models.base import ModelBase
from django.db.models.functions import Now
from django.utils import timezone


NAME = 'udjango'
DB_FILE = NAME + '.db'




def main():
setup()
logger = logging.getLogger(__name__)


class Widget(models.Model):
name = models.CharField(max_length=200)
date_created = models.DateTimeField()


def __str__(self):
return self.name


syncdb(Widget)


Widget.objects.create(name='spline', date_created=Now())
sleep(1)
Widget.objects.create(name='reticulator', date_created=Now())
sleep(1)
Widget.objects.create(name='tardis', date_created=Now())
sleep(5)
Widget.objects.create(name='sonic screwdriver', date_created=Now())
sleep(1)


cutoff_time = Now() - timedelta(seconds=5)
for widget in Widget.objects.filter(date_created__lt=cutoff_time):
logger.info(widget.name)




def setup():
with open(DB_FILE, 'w'):
pass  # wipe the database
settings.configure(
USE_TZ=True,
DEBUG=True,
DATABASES={
DEFAULT_DB_ALIAS: {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': DB_FILE}},
LOGGING={'version': 1,
'disable_existing_loggers': False,
'formatters': {
'debug': {
'format': '[%(levelname)s]'
'%(name)s.%(funcName)s(): %(message)s',
'datefmt': '%Y-%m-%d %H:%M:%S'}},
'handlers': {
'console': {
'level': 'DEBUG',
'class': 'logging.StreamHandler',
'formatter': 'debug'}},
'root': {
'handlers': ['console'],
'level': 'INFO'},
'loggers': {
"django.db": {"level": "INFO"}}})
app_config = AppConfig(NAME, sys.modules['__main__'])
apps.populate([app_config])
django.setup()
original_new_func = ModelBase.__new__


@staticmethod
def patched_new(cls, name, bases, attrs):
if 'Meta' not in attrs:
class Meta:
app_label = NAME
attrs['Meta'] = Meta
return original_new_func(cls, name, bases, attrs)
ModelBase.__new__ = patched_new




def syncdb(model):
""" Standard syncdb expects models to be in reliable locations.


Based on https://github.com/django/django/blob/1.9.3
/django/core/management/commands/migrate.py#L285
"""
connection = connections[DEFAULT_DB_ALIAS]
with connection.schema_editor() as editor:
editor.create_model(model)




main()

我最近几年没有看到这个问题,所以在大多数情况下,这可能不值得麻烦。

使用 created__gte而不是 created__lt,如果你想得到超过5小时