You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I'm using Django 2.2.6 and I found that ComputedFields are not updated in the database when saving models unless these fields have been accessed before saving.
It looks like ComputedFields use the pre_safe signal to compute and store the values in the model's __dict__ just before the model is persisted in the database. The problem is that this is too late. At the time pre_save is triggered, the ComputedField has already been classified as "deferred" in Model.save(), thus it is not included in update_fields and not part of the generated SQL statement.
However, if the ComputedField has been accessed before saving, the computed value is already stored in __dict__ when the deferred fields are determined. Thus, the field is included in update_fields and it works as expected.
A simple, but easy to forget workaround is to explicitly access all ComputedFields before saving a model instance:
Can you provide an example of code that shows this behavior? I don't have an exact test for this, but there is a test that does a .objects.create and then a get using the computed value. This shows it was stored in the DB, and seems like it would mirror the same behavior as not explicitly accessing the computed field on the object.
I'm using Django 2.2.6 and I found that ComputedFields are not updated in the database when saving models unless these fields have been accessed before saving.
It looks like ComputedFields use the
pre_safe
signal to compute and store the values in the model's__dict__
just before the model is persisted in the database. The problem is that this is too late. At the timepre_save
is triggered, the ComputedField has already been classified as "deferred" inModel.save()
, thus it is not included inupdate_fields
and not part of the generated SQL statement.However, if the ComputedField has been accessed before saving, the computed value is already stored in
__dict__
when the deferred fields are determined. Thus, the field is included inupdate_fields
and it works as expected.A simple, but easy to forget workaround is to explicitly access all ComputedFields before saving a model instance:
A potential fix is to use the
post_init
signal to trigger value computation as soon as a model instance is created:I could do a PR but since I am relatively new to Django I am not sure if my fix has any unintended side effects.
The text was updated successfully, but these errors were encountered: