# Refresh \`GeneratedField\` column when calling save

**URL:** <https://forum.djangoproject.com/t/refresh-generatedfield-column-when-calling-save/36437>\
**Category:** ORM\
**Created:** [November 15, 2024, 5:18am UTC](https://forum.djangoproject.com/t/refresh-generatedfield-column-when-calling-save/36437 "2024-11-15T05:18:16Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![jamesbeith](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/jamesbeith/32/25179_2.png) [@jamesbeith](https://forum.djangoproject.com/u/jamesbeith)\
**Post date:** [November 15, 2024, 5:18am UTC](https://forum.djangoproject.com/t/refresh-generatedfield-column-when-calling-save/36437/1 "2024-11-15T05:18:16Z")

</div>

When using a `GeneratedField` there’s the follow caveat mentioned in the docs.

> Since the database always computed the value, the object must be reloaded to access the new value after `save()`, for example, by using `refresh_from_db()`.

Taking [this `Square` model example](https://docs.djangoproject.com/en/5.1/releases/5.0/#database-generated-model-field) from the Django 5.0 release notes, we can see that when we create a square instance the generated `area` is returned for us and set on the in-memory instance (note, this is true when using either the model manager `create()` method or calling `save()` on an unsaved model instance). However, when we update and call `save()` on that instance, as mentioned, the generated `area` is not updated and we have to explicitly use `refresh_from_db()`. For example:

```python
>>> square = models.Square.objects.create(side=2)
# INSERT INTO "square" ("side") VALUES (2) RETURNING "square"."id", "square"."area";

>>> square.area
4

>>> square.side = 5

>>> square.save()
# UPDATE "square" SET "side" = 5 WHERE "square"."id" = 1;

>>> square.area
4

>>> square.refresh_from_db()
# SELECT "square"."id", "square"."side", "square"."area" FROM "square" WHERE "square"."id" = 1 LIMIT 21;

>>> square.area
25

```

Would it be feasible to add support into Django to get that generated `area` field updated on the in-memory instance as part of calling save by making use of the **RETURNING** SQL clause? Perhaps this could happen when using the `update_fields` kwarg or maybe more explicitly with a new `returning_fields` kwarg? Dummy example:

```python
>>> square.save(update_fields=["side", "area"])
# UPDATE "square" SET "side" = 5 WHERE "square"."id" = 1 RETURNING "square"."side", "square"."area";

>>> square.save(returning_fields=["area"])
# UPDATE "square" SET "side" = 5 WHERE "square"."id" = 1 RETURNING "square"."area";

```

---

<div class="post-metadata">

**Author:** ![charettes](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/charettes/32/27_2.png) [@charettes](https://forum.djangoproject.com/u/charettes)\
**Post date:** [November 15, 2024, 5:33pm UTC](https://forum.djangoproject.com/t/refresh-generatedfield-column-when-calling-save/36437/2 "2024-11-15T17:33:03Z")

</div>

Hello @jamesbeith!

In terms of what the API should look like I believe that a distinct `returning_fields` might be preferable to avoid ambiguity but `update_fields` is also technically feasible given it’s currently a noop for `GeneratedField`.

This feature request has a bit of overlap with the accepted one about [adding support for `update(returning)`](https://code.djangoproject.com/ticket/32406) so could I see them go hand-in-hand at least in how we expose both features and how they reuse the same compile logic. In this case though we don’t have `update` API collisions for op-tin in as `save` doesn’t special case `**kwargs`.

You might find [the proposed patch for the above](https://github.com/django/django/pull/17307/) interesting as it implements the required bits of the compiler except that [it doesn’t use the API that was initially agreed upon](https://groups.google.com/g/django-developers/c/qQ5DT91nBLM). Given this feature might be useful for non-`GeneratedField` as well (e.g. imagine some user defined triggers) I think it warrants a specialized kwarg.

So to answer your question, yes it’s doable there is interest. What’s left to do to make things happen though is for someone to shepherd the changes to mergeable state which will inevitably involve a bit of bike shedding around what the exact API should look like. If that’s something that is of interest to you [please dive in](https://docs.djangoproject.com/en/5.1/internals/contributing/writing-code/) and we’ll do our best to support you through the journey.

---

<div class="post-metadata">

**Author:** ![charettes](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/charettes/32/27_2.png) [@charettes](https://forum.djangoproject.com/u/charettes)\
**Post date:** [November 15, 2024, 5:49pm UTC](https://forum.djangoproject.com/t/refresh-generatedfield-column-when-calling-save/36437/3 "2024-11-15T17:49:38Z")

</div>

Digging a bit more I also found [this long standing ticket about having fields that expressions automatically refreshed using `RETURNING`](https://code.djangoproject.com/ticket/27222).

This made me think we might want to have the kwarg default to all fields assigned as expressions if not specified to resolve the ticket in the same iteration?

In other words doing something like

```python
author.book_count = F("book_count") + 1
author.save()

```

Would default `returning_fields` to `{"book_count"}` assuming it’s supported by the backend.

I thought we could also name he kwarg `refresh_fields` but I think it’s worth keeping as an alternative name for now given _refresh_ is currently tied to the concept of a doing a distinct query to retrieve data which is not the case when using `RETURNING`.
