django-models-logging

Add logging of models from save, delete signals


Keywords
django, logging, history, models
License
MIT
Install
pip install django-models-logging==2.3.3

Documentation

Django Models Logging

This package is for logging every changes in your models in this format:

{
    field_name: {
        "old":  `old_value`, "new":  `new_value` | `None` if this is delete action
    }
}

Example

{
  "price": {
    "old": "2425",
    "new": "645"
  },
  "name": {
    "old": "ProductName",
    "new": "NewProductNmae"
  }
}

USING

Add 'models_logging' at the end of INSTALLED_APPS in settings.py! This is important because models connect to save and init signals when apps is ready

  1. Install using pip - pip install django-models-logging

INSTALLED_APPS = (
    ...,
    'models_logging',
)

If request.user is not represented by AUTH_USER_MODEL in your application then you can set up a custom Users model:

LOGGING_USER_MODEL = 'yourapp.Users'
# By default, LOGGING_USER_MODEL = AUTH_USER_MODEL
  1. make migrations
  2. add the models you want to log in settings.py, format:
LOGGING_MODELS = (
    'app.ClassName',    # logging only for this model
    'another_app'     # logging of all models in this app
)

Sometimes object.save() operation can be called many times per 1 request. Per each .save() models_logging creates Change, so your database can quickly grow to a very large size for prevent this "bug" you can add middleware in settings.py

MIDDLEWARE = (
    ...,
    'models_logging.middleware.LoggingStackMiddleware',     # it merge all changes of object per request
)

or use context_manager from models_logging.utils in your view or script

from models_logging.utils import create_merged_changes

def your_script():
    with create_merged_changes():
        ...

You can add model for ignore logging settings.py

LOGGING_EXCLUDE = (
    'app'     # ignore logging of all models in this app
    'another_app.Model'     # ignore logging for this model
)

Also you can set up permission for the logging records Make func (it will be called in admin) or bool settings.py

def can_revert(request, obj):
    return request.user.username == 'myusername'

LOGGING_REVERT_IS_ALLOWED = can_revert
LOGGING_CAN_DELETE_REVISION = can_revert
LOGGING_CAN_DELETE_CHANGES = False
LOGGING_CAN_CHANGE_CHANGES = True

in models you can set attributes:

LOGGING_IGNORE_FIELDS = ()  # to ignore changes of some fields

# OR

LOGGING_ONLY_FIELDS  = ()    # to save changes of only those fields

If you want to watch changes in admin/history of your object you can use models_logging.admin.HistoryAdmin

from models_logging.admin import HistoryAdmin


class YourAdminModel(HistoryAdmin):
    history_latest_first = False    # latest changes first
    inline_models_history = '__all__'   # __all__ or list of inline models for this ModelAdmin

You can implement your own JSONEncoder and set path to it in django settings

LOGGING_JSON_ENCODER = 'path.to.your.JsonEncoder'

Version > 1.0 is incompatible with old versions (requires django >= 2.0) For django <= 2.0 use 0.9.7 version Version > 2.0 is incompatible with old versions (requires django >= 3.1)

PS: This module is not optimal as a backup for your database. If you try to recover thousands of changes this will be very slow.