Skip to content

Overriding save()

Employees approve an application in the table on its animal's page. Reset the sample data, so Cobalt has one adoption application and Pepper has two:

shell
uv run manage.py seed --reset

Open Cobalt in the admin, set their application's status to Approved, and click Save.

In the list of animals, Cobalt is still Available.

Info

Once an application is approved, the animal shouldn't take more applications. That doesn't happen automatically, so we need to set the animal's status ourselves.

Our Own save() Method

Override the save() method on AdoptionApplication, below __str__():

animals/models.py
    def save(self, **kwargs):
        super().save(**kwargs)

Marking the Animal as Pending

animals/models.py
    def save(self, **kwargs):
        super().save(**kwargs)
        # An approved application marks its animal pending.
        if (
            self.status == self.Status.APPROVED
            and self.animal.status == Animal.Status.AVAILABLE
        ):
            self.animal.status = Animal.Status.PENDING
            # Write the status column only, not the whole animal record.
            self.animal.save(update_fields=["status"])

Open Pepper, set the status of one of their applications to Approved, and click Save. Pepper is now Adoption pending.

Info

A post_save signal triggers automatically after a model has been saved to the database. It's often used to update related models.

What save() Doesn't Do

Our save() only handles an approval. If an employee declines an application after approving it, or deletes it, the animal stays pending, and its status has to be changed back by hand.

Our check also reads the application's status in memory. A call such as save(update_fields=["message"]) writes only the columns in update_fields. So an approval that was never saved can still mark the animal pending. Nothing in our app saves an application that way.

Warning

Nothing stops a second application for the same animal from being approved. We'll fix that next.