Welcome | Get started | Dive | Contribute | Topics | Reference | Changes | More

changes: Keep track of changes in the database

The lino.modlib.changes plugin adds functionality for recording changes to individual database rows into a database table.

See watch – Watching database changes for an illustrative demo project.

Table of contents:

What it does

The plugin does the following:

  • define the Change model.

  • define the watch_changes() function

  • define a background task delete_older_changes

  • add a menu entry Explorer ‣ System ‣ Changes

  • add a show_changes button () to every watched model

Usage

As the application developer you must explicitly declare which models you want to watch. You do this in the setup_actions method of your Site class. For example here is an excerpt of the Site class in lino_noi.lib.noi.settings:

def setup_actions(self):
    super().setup_actions()
    from lino.modlib.changes.utils import watch_changes as wc
    wc(self.modules.tickets.Ticket, ignore=['_user_cache'])
    wc(self.modules.comments.Comment, master_key='owner')
lino.modlib.changes.watch_changes(model, ignore=[], master_key=None, **options)

Declare the specified model to be watched for changes.

ignore, if specified, should be an iterable of field names to be ignored. It may be be specified as a string with a space-separated list of field names.

It is allowed to call watch_changes() multiple times per model.

Models for which watch_changes() has been called at least once during startup will have their Model.change_watcher_spec set to an instance of WatcherSpec.

Plugin configuration

changes.remove_after

Database model

class lino.modlib.changes.Change

Django model to represent a registered change in the database.

Each database change of a watched object will generate one Change record.

object

The database object that has been modified.

master

The database object that acts as “master”.

class lino.modlib.changes.Changes
class lino.modlib.changes.ChangesByObject

Show the history of changes in the current database row.

class lino.modlib.changes.ChangesByMaster

Show the history of changes in the current database row and related data.

class lino.modlib.changes.ChangeTypes

The list of possible choices for the type field of a Change.

Tested code examples

Side note: Code snippets (lines starting with >>>) in this document get tested as part of our development workflow. The following initialization snippet tells you which demo project is being used in this document.

>>> from lino import startup
>>> startup('lino_book.projects.noi1r.settings')
>>> from lino.api.doctest import *
>>> ses = rt.login("robin")
>>> translation.activate('en')
>>> rt.show(changes.ChangeTypes)
======= ============== ==============
 value   name           text
------- -------------- --------------
 C       create         Create
 U       update         Update
 D       delete         Delete
 R       remove_child   Remove child
 A       add_child      Add child
 M       merge          Merge
======= ============== ==============
>>> ba = comments.Comments.get_action_by_name('show_changes')
>>> ba.action
<lino.core.actions.ShowSlaveTable show_changes>
>>> print(ba.action.button_text)

>>> print(ba.action.help_text)
Show the history of changes in the current database row.
>>> ba = tickets.Tickets.get_action_by_name('show_changes')
>>> print(ba.action.button_text)

>>> print(ba.action.help_text)
Show the history of changes in the current database row and related data.