Skip to content

T53716: Add DurationField support (serialization, filtering, tests) - #285

Open
SotirisDimitrakoulakos wants to merge 1 commit into
CodeYellowBV:masterfrom
SotirisDimitrakoulakos:master
Open

T53716: Add DurationField support (serialization, filtering, tests)#285
SotirisDimitrakoulakos wants to merge 1 commit into
CodeYellowBV:masterfrom
SotirisDimitrakoulakos:master

Conversation

@SotirisDimitrakoulakos

@SotirisDimitrakoulakos SotirisDimitrakoulakos commented Sep 3, 2026

Copy link
Copy Markdown

Initial Problem — Models with a Django models.DurationField were unusable through the API:

  • any GET/POST/PUT response containing a duration led to 500 (TypeError: datetime.timedelta is not JSON serializable)
  • filtering on a duration field led to 418 (no filter class for the field type)
  • writing only worked on PostgreSQL (whose interval parser tolerates the raw string); on MySQL/SQLite every duration write crashed at save()

Changes

  • binder/json.py: register datetime.timedelta in SERIALIZERS - django.utils.duration.duration_string. Wire format: "[D] [HH:]MM:SS[.uuuuuu]" (e.g. 00:30:00, 2 03:04:05, -1 23:30:00) — exactly what parse_duration/to_python accept, so GET output round-trips on PUT.
  • binder/models.py: new DurationFieldFilter (auto-registered via FieldFilter.__subclasses__()), parses with django.utils.dateparse.parse_duration, same qualifier set as the Date/DateTime/Time filters (in, gt, gte, lt, lte, range, isnull); invalid value leads to 418 RequestError like all other filters.
  • binder/views.py: the generic write path (_store_field) now stores the parsed value for DurationField instead of the raw string. Previously to_python() was already called (for validation) but its result was discarded and the raw string was stored — which only works on PostgreSQL (its interval parser tolerates the string at save time). On MySQL/SQLite, get_db_prep_value() leads to duration_microseconds(), performs attribute access on a timedelta and crashes on a str, so every duration write 500s on those backends.
  • Tests: new Truck test model + view (one DurationField, one nullable) and 12 new tests — serializer unit test (4 formats incl. multi-day and negative), POST/GET/PUT round-trip, default value, 400/418 write error paths, and exact/gte/range/invalid filter tests.
  • changelog/T53716

Comment thread binder/views.py
}
})
# Store the parsed value instead of the raw string: non-native
# backends (MySQL, SQLite) call duration_microseconds() which does

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that we don't support SQLite. We only support Postgres and MySQL (and we don't use the latter anyway).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants