4

I'm using the Peewee ORM in my Flask website and I now want to build a versioned/history table so that I can track changes to records. I'm following the basic SQL structure from this SO answer.

So to do this I need some way inserting triggers for the .save() methods of the fields, and I think I once read about some kind of before_save and after_save hooks, but I can't find anything like that anymore.

So does anybody know how I can hook up extra methods to saving, updating and deleting records, as well as creating tables in the Peewee ORM?

All tips are welcome!

Community
  • 1
  • 1
kramer65
  • 50,427
  • 120
  • 308
  • 488
  • Does this answer your question? [Change the column order in a table for a subclassed model](https://stackoverflow.com/questions/30036817/change-the-column-order-in-a-table-for-a-subclassed-model) – coccoinomane Dec 01 '22 at 15:18

2 Answers2

8

It is included as part of the signals extension:

http://docs.peewee-orm.com/en/latest/peewee/playhouse.html#signal-support

coleifer
  • 24,887
  • 6
  • 60
  • 75
  • please let me know if you'd like me to contribute this BaseModel pre_save timestamping example to the signals docs. see answer below – Kermit May 19 '22 at 12:32
1

Here is an example of playhouse.signals.pre_save in action. Assuming all Model classes inherit from BaseModel, this adds timestamps to every table.

import datetime as dt
from playhouse.signals import Model, pre_save
from peewee import DateTimeField


def timezone_now():
    """Infers timezone from user's OS. It knows EDT vs EST."""
    return dt.datetime.now(dt.timezone.utc).astimezone()


class BaseModel(Model):
    time_created = DateTimeField()
    time_updated = DateTimeField()

    class Meta:
        database = get_db()
    
    # Fetch as human-readable timestamps
    def created_at(self):
        return self.time_created.strftime('%Y%b%d_%H:%M:%S')
    def updated_at(self):
        return self.time_updated.strftime('%Y%b%d_%H:%M:%S')
    

@pre_save(sender=BaseModel)
def add_timestamps(model_class, instance, created):
    if (created==True):
        instance.time_created = timezone_now()
    instance.time_updated = timezone_now()
    # intentionally no `return`
Kermit
  • 4,922
  • 4
  • 42
  • 74