Skip to content

Commit

Permalink
add WithHistory abstract model (#37)
Browse files Browse the repository at this point in the history
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
  • Loading branch information
joshuadavidthomas and pre-commit-ci[bot] committed May 21, 2024
1 parent 0d59e01 commit 34d52b5
Show file tree
Hide file tree
Showing 6 changed files with 85 additions and 1 deletion.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ and this project attempts to adhere to [Semantic Versioning](https://semver.org/

## [Unreleased]

### Added

- Added a `WithHistory` abstract model for integrating `django-simple-history` `HistoricalRecords`.

## [0.4.0]

### Added
Expand Down
4 changes: 3 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ dev = [
"coverage[toml]",
"django-stubs",
"django-stubs-ext",
"django-twc-toolbox[cuid,history]",
"faker",
"hatch",
"mypy",
Expand All @@ -60,6 +61,7 @@ docs = [
"sphinx-copybutton",
"sphinx-inline-tabs"
]
history = ["django-simple-history"]
lint = ["pre-commit"]

[project.urls]
Expand Down Expand Up @@ -131,7 +133,7 @@ module = ["django_twc_toolbox.*.migrations.*", "tests.*"]

[[tool.mypy.overrides]]
ignore_missing_imports = true
module = ["charidfield.*", "cuid.*"]
module = ["charidfield.*", "cuid.*", "simple_history.*"]

[tool.mypy_django_plugin]
ignore_missing_model_attributes = true
Expand Down
31 changes: 31 additions & 0 deletions src/django_twc_toolbox/models.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
from __future__ import annotations

from importlib.util import find_spec

from django.db import models

if find_spec("simple_history"):
from simple_history.models import HistoricalRecords
else:
HistoricalRecords = None


class TimeStamped(models.Model):
"""
Expand Down Expand Up @@ -61,3 +68,27 @@ def save(self, *args, **kwargs) -> None:

def is_edited(self) -> bool:
return self.created_at != self.updated_at


class WithHistory(models.Model):
"""
Abstract model for adding historical records to a model.
"""

history = HistoricalRecords(inherit=True)

class Meta:
abstract = True

def save(self, *args, without_history: bool = False, **kwargs) -> None:
if without_history:
self.save_without_history(*args, **kwargs)
else:
super().save(*args, **kwargs)

def save_without_history(self, *args, **kwargs) -> None:
self.skip_history_when_saving = True
try:
self.save(*args, **kwargs)
finally:
del self.skip_history_when_saving
2 changes: 2 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,10 @@ def pytest_configure(config):

TEST_SETTINGS = {
"INSTALLED_APPS": [
"django.contrib.auth",
"django.contrib.contenttypes",
"django_twc_toolbox",
"simple_history",
"tests.dummy",
]
}
6 changes: 6 additions & 0 deletions tests/dummy/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,16 @@

from django.db import models

from django_twc_toolbox.models import WithHistory


class DateOrderableModel(models.Model):
date = models.DateField()


class DateTimeOrderableModel(models.Model):
date = models.DateTimeField()


class ModelWithHistory(WithHistory):
name = models.CharField(max_length=255)
39 changes: 39 additions & 0 deletions tests/test_models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
from __future__ import annotations

import pytest
from model_bakery import baker

pytestmark = pytest.mark.django_db


def test_with_history():
dummy = baker.make("dummy.ModelWithHistory")

assert dummy.history.count() == 1


def test_save_without_history_kwarg():
dummy = baker.make("dummy.ModelWithHistory")

assert dummy.history.count() == 1

dummy.name = "New name"
dummy.save(without_history=True)

assert dummy.history.count() == 1

dummy.name = "I'm not a dummy"
dummy.save()

assert dummy.history.count() == 2


def test_save_without_history_method():
dummy = baker.make("dummy.ModelWithHistory")

assert dummy.history.count() == 1

dummy.name = "You're a dummy"
dummy.save_without_history()

assert dummy.history.count() == 1

0 comments on commit 34d52b5

Please sign in to comment.