From 1acb00b26da13165e967bf2354fc917e38c382e4 Mon Sep 17 00:00:00 2001 From: Tim Graham Date: Tue, 23 Sep 2025 12:36:49 -0400 Subject: [PATCH] Fixed #36616 -- Added DatabaseOperations.adapt_durationfield_value(). --- django/db/backends/base/operations.py | 11 +++++++++++ django/db/backends/oracle/operations.py | 3 +++ django/db/backends/postgresql/operations.py | 3 +++ django/db/models/fields/__init__.py | 8 ++------ docs/releases/6.1.txt | 4 +++- 5 files changed, 22 insertions(+), 7 deletions(-) diff --git a/django/db/backends/base/operations.py b/django/db/backends/base/operations.py index 16a6296f9b..9822a7fbb1 100644 --- a/django/db/backends/base/operations.py +++ b/django/db/backends/base/operations.py @@ -9,6 +9,7 @@ from django.conf import settings from django.db import NotSupportedError, transaction from django.db.models.expressions import Col from django.utils import timezone +from django.utils.duration import duration_microseconds from django.utils.encoding import force_str @@ -564,6 +565,16 @@ class BaseDatabaseOperations: return None return str(value) + def adapt_durationfield_value(self, value): + """ + Transform a timedelta value into an object compatible with what is + expected by the backend driver for duration columns (by default, + an integer of microseconds). + """ + if value is None: + return None + return duration_microseconds(value) + def adapt_timefield_value(self, value): """ Transform a time value to an object compatible with what is expected diff --git a/django/db/backends/oracle/operations.py b/django/db/backends/oracle/operations.py index bc152c4e6e..e5da5928f9 100644 --- a/django/db/backends/oracle/operations.py +++ b/django/db/backends/oracle/operations.py @@ -608,6 +608,9 @@ END; return Oracle_datetime.from_datetime(value) + def adapt_durationfield_value(self, value): + return value + def adapt_timefield_value(self, value): if value is None: return None diff --git a/django/db/backends/postgresql/operations.py b/django/db/backends/postgresql/operations.py index 7cd868d789..91456e3daf 100644 --- a/django/db/backends/postgresql/operations.py +++ b/django/db/backends/postgresql/operations.py @@ -330,6 +330,9 @@ class DatabaseOperations(BaseDatabaseOperations): def adapt_datetimefield_value(self, value): return value + def adapt_durationfield_value(self, value): + return value + def adapt_timefield_value(self, value): return value diff --git a/django/db/models/fields/__init__.py b/django/db/models/fields/__init__.py index ee7a30cc30..f12ae97968 100644 --- a/django/db/models/fields/__init__.py +++ b/django/db/models/fields/__init__.py @@ -30,7 +30,7 @@ from django.utils.dateparse import ( parse_duration, parse_time, ) -from django.utils.duration import duration_microseconds, duration_string +from django.utils.duration import duration_string from django.utils.functional import Promise, cached_property from django.utils.ipv6 import MAX_IPV6_ADDRESS_LENGTH, clean_ipv6_address from django.utils.text import capfirst @@ -1890,11 +1890,7 @@ class DurationField(Field): ) def get_db_prep_value(self, value, connection, prepared=False): - if connection.features.has_native_duration_field: - return value - if value is None: - return None - return duration_microseconds(value) + return connection.ops.adapt_durationfield_value(value) def get_db_converters(self, connection): converters = [] diff --git a/docs/releases/6.1.txt b/docs/releases/6.1.txt index be05350d94..edfdacf6b7 100644 --- a/docs/releases/6.1.txt +++ b/docs/releases/6.1.txt @@ -243,7 +243,9 @@ Database backend API This section describes changes that may be needed in third-party database backends. -* ... +* The ``DatabaseOperations.adapt_durationfield_value()`` hook is added. If the + database has native support for ``DurationField``, override this method to + simply return the value. Miscellaneous -------------