Skip to content

Fixed #31506 -- Documented DateField and timedelta behavior with ExpressionWrapper.#19947

Merged
jacobtylerwalls merged 1 commit intodjango:mainfrom
forwardyoung:ticket-31506-docs
Nov 26, 2025
Merged

Fixed #31506 -- Documented DateField and timedelta behavior with ExpressionWrapper.#19947
jacobtylerwalls merged 1 commit intodjango:mainfrom
forwardyoung:ticket-31506-docs

Conversation

@forwardyoung
Copy link
Copy Markdown
Contributor

@forwardyoung forwardyoung commented Oct 12, 2025

Add warning in ExpressionWrapper documentation about date/datetime type differences when using timedelta on PostgreSQL and MySQL. Included Cast() and integer arithmetic solutions.

Trac ticket number

ticket-31506

Branch description

It documents the behavioral differences across database backends when using DateField with timedelta inside an ExpressionWrapper.

To address the issue where arithmetic operations on date/time fields in PostgreSQL and MySQL can return a datetime type instead of a date, a warning has been added to the ExpressionWrapper documentation. It also provides solutions, such as using the Cast() function, to help developers avoid unintended type mismatches.

Checklist

  • This PR targets the main branch.
  • The commit message is written in past tense, mentions the ticket number, and ends with a period.
  • I have checked the "Has patch" ticket flag in the Trac system.
  • I have added or updated relevant tests.
  • I have added or updated relevant docs, including release notes if applicable.
  • I have attached screenshots in both light and dark modes for any UI changes.

@github-actions
Copy link
Copy Markdown

Hello! Thank you for your contribution 💪

As it's your first contribution be sure to check out the patch review checklist.

If you're fixing a ticket from Trac make sure to set the "Has patch" flag and include a link to this PR in the ticket!

If you have any design or process questions then you can ask in the Django forum.

Welcome aboard ⛵️!

@forwardyoung forwardyoung changed the title Fixed #31506 -- Documented DateField and timedelta behavior with Fixed #31506 -- Documented DateField and timedelta behavior with ExpressionWrapper. Oct 12, 2025
@forwardyoung
Copy link
Copy Markdown
Contributor Author

forwardyoung commented Oct 12, 2025

https://github.com/django/django/actions/runs/18447405998/job/52556055766?pr=19947
I think timedelta should be added to the spelling_word_list file.

@marcorichetta
Copy link
Copy Markdown
Contributor

django/django/actions/runs/18447405998/job/52556055766?pr=19947 I think timedelta should be added to the spelling_word_list file.

Per the contributing docs on spelling check, I think it would be correct to enclose them in double grave accents (``), as the first alternative suggests.
If that still fails, then it should be ok to add the word to spelling_wordlist.txt.

Copy link
Copy Markdown
Member

@jacobtylerwalls jacobtylerwalls left a comment

Choose a reason for hiding this comment

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

Thanks for the PR! Will be great to add help here to prevent paper cuts. 👍

A concern I have is that adding this level of detail to the ExpressionWrapper section could reinforce a misunderstanding about what it does.

The problem surfaces when using simpler expressions like F(), as in your example. The reporter expected this problem to be solved via ExpressionWrapper, but that was a misunderstanding. ExpressionWrapper only helps you set output_field, which is an ORM concept[0], not a database concept, on expressions that don't have output_field. If we are going to add admonitions to a tool's docs about when not to use that tool, I'd prefer the advice be general instead of highly specialized to date fields.

The advice you present here to use Cast or integer arithmetic or custom fields is correct, but we could present that in the DateField docs instead, where there are similar warnings about other paper cuts, rather than detouring into ExpressionWrapper.

That said, I do think we should clarify in the ExpressionWrapper docs that it doesn't do any casting in the database.

So, to pull it all together, my recommendation is to:

  • clarify in ExpressionWrapper how it differs from Cast
  • move the advice about creating a custom model field to the docs for output_field, where it suggests output_field is "only required when Django is unable to automatically determine the result’s field type". That's true, but it is also helpful in cases where you want to encapsulate the python-side casting behavior, which you can do with custom fields, which you point out here very well.
  • move the admonition about postgres/mysql datefield arithmetic behavior to the DateField admonitions, keeping your integer arithmetic alternative example

Thanks again, and welcome aboard! ⛵


[0] - The fact that in at least one case output_field actually entails a database cast is a bug that people are likely relying on!

@forwardyoung
Copy link
Copy Markdown
Contributor Author

Hi @jacobtylerwalls, sorry for the late update!
I’ve revised the PR according to your feedback.
Could you please take another look when you have time?

Copy link
Copy Markdown
Member

@jacobtylerwalls jacobtylerwalls left a comment

Choose a reason for hiding this comment

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

Thank you, updates look great, just some last edits. Also mind fixing the merge conflicts?

@forwardyoung
Copy link
Copy Markdown
Contributor Author

forwardyoung commented Nov 13, 2025

Thank you, updates look great, just some last edits. Also mind fixing the merge conflicts?

@jacobtylerwalls Of course! I’ll take a close look at your comments. Thanks a lot:)

Copy link
Copy Markdown
Member

@jacobtylerwalls jacobtylerwalls left a comment

Choose a reason for hiding this comment

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

Thank you @forwardyoung! Should be good to go once the missing backticks and line lengths lints are fixed 👍

@forwardyoung
Copy link
Copy Markdown
Contributor Author

@jacobtylerwalls
Thank you so much!
Your comments were really meaningful. I’ll make the changes right away 🏃🏻‍♀️

Copy link
Copy Markdown
Member

@jacobtylerwalls jacobtylerwalls left a comment

Choose a reason for hiding this comment

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

Yay, checks are passing now. I gave this a final read and noticed one slight inconsistency, can you let me know if you agree with this suggestion?

…abase casts.

Added warning in DateField documentation about type differences when using
timedelta on PostgreSQL and MySQL. Mentioned Cast() and integer arithmetic
solutions.
Copy link
Copy Markdown
Member

@jacobtylerwalls jacobtylerwalls left a comment

Choose a reason for hiding this comment

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

Great, the latest rounds of changes read perfectly. Thanks for being so responsive. Welcome aboard! ⛵

@jacobtylerwalls jacobtylerwalls merged commit 55af474 into django:main Nov 26, 2025
10 of 30 checks passed
@forwardyoung
Copy link
Copy Markdown
Contributor Author

@jacobtylerwalls It’s all thanks to you:)
I’ll keep contributing🙌

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants