djangomodelchoicefield

get_field_display() does not return string after saving it


Hereby my (simplified) situation. When I change a choicefield from one to the other, I want to record a message saying

"Field changed from (previous) to (new)"

In parenthesis I'd like the actual label of the field, so in case of the example below that should be "Field changed from Open to Completed". However, for some reason I am only able to generate

"Field changed from Open to 2"

I am baffled why this happens given that I use the exact same code. Any ideas?

class Task(Record):

    class Status(models.IntegerChoices):
        OPEN = 1, "Open"
        COMPLETED = 2, "Completed"
    status = models.IntegerField(choices=Status.choices, db_index=True, default=1)

Then in my views I try to do this:

    if request.POST["status"] == 2:
        description = "Status changed from " + info.get_status_display() + " → "
        # This works fine, returning "Status changed from Open → "
        info.status = request.POST.get("status_change")
        info.save()
        description = description + str(info.get_status_display())
        # Yet for some reason this fails, and I end up with an integer (2)! even though I use the same syntax

Solution

  • When you save a model, its model state is not reinitialized. For most cases this works just fine, but to be precise: from_db_value() is not applied to fields and this is necessary to convert raw data you just submitted to the representation format you're used to.

    Calling a model's refresh_from_db() triggers a model reload from the database, which in turn calls from_db_value for each field.