我正在尝试编写一个 Django 查询的小部件是超过5小时,我有点迷路了。小部件模型有一个用小部件的创建时间填充的 DateTimeField。
DateTimeField
如果 Widget是您的模型的名称,并且它有一个名为 created的 DateTimeField 属性,那么查询将是:
Widget
created
from datetime import datetime, timedelta time_threshold = datetime.now() - timedelta(hours=5) results = Widget.objects.filter(created__lt=time_threshold)
请注意,created__lt的意思是“创建小于”。
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(...
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():
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()功能获取数据库中的当前时间。
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小时
created__gte