#36855: Field.pre_save() called twice during save() in Django 6.0 when inserting
new records
---------------------------------+------------------------------------
Reporter: Nino Walker | Owner: (none)
Type: Bug | Status: new
Component: Documentation | Version: 6.0
Severity: Release blocker | Resolution:
Keywords: pre_save | Triage Stage: Accepted
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
---------------------------------+------------------------------------
Changes (by Jacob Walls):
* component: Database layer (models, ORM) => Documentation
* keywords: => pre_save
* severity: Normal => Release blocker
* stage: Unreviewed => Accepted
Comment:
Thanks for the report. This was discussed just a couple days ago, but I'm
happy to have a new ticket for clarity.
I suggested documenting that `pre_save()` functions should be idempotent
in ticket:36847#comment:11, but Simon pointed out we should update our own
`DateField.pre_save` implementations first. (They aren't technically
idempotent, but they're pretty close. They're certainly side-effect free.)
Some of the use cases you mention seem a better fit for the `pre_save`
signal than the `pre_save()` field method, but I'd have to look closer.
Committing to support for non-idempotent `pre_save()` methods is a new
feature that would merit some discussion elsewhere on the forum or django
/new-features. Take the example of another field method:
`ArrayField.get_db_prep_value` calls `get_db_prep_value()` on each of its
base fields. For that reason if `get_db_prep_value()` had side effects,
that would be a problem.
We likely should have documented this as a minor incompatible change in
6.0, so I'm reframing this as a documentation fix for the release notes
for now. Django has a grain, and one way to follow the grain is ensure
that `pre_save()` only preprocesses single values without side effects.
Side effects can be orchestrated in many other ways.
--
Ticket URL: <
https://code.djangoproject.com/ticket/36855#comment:1>