From 7173f17317bcfa8ebbabadbf7d650d1d40d42fc1 Mon Sep 17 00:00:00 2001 From: Nicolas Delaby Date: Fri, 24 Mar 2023 11:52:09 +0100 Subject: [PATCH] Deprecate StateLog model, to instead bring your own model. This is an implementation that support the idea exposed in https://github.com/jazzband/django-fsm-log/discussions/133 It's still a Draft, I'm open for any feedback more specifically around the names. Not tested yet with a real project. It's meant to be completely backward compatible. --- README.md | 58 ++++++++++++++----- django_fsm_log/admin.py | 19 ++++-- django_fsm_log/apps.py | 4 +- django_fsm_log/backends.py | 27 ++++++--- django_fsm_log/conf.py | 9 ++- django_fsm_log/managers.py | 25 ++++++-- django_fsm_log/migrations/0001_initial.py | 2 +- .../migrations/0004_auto_20190131_0341.py | 1 + django_fsm_log/models.py | 28 +++++++-- pyproject.toml | 4 +- tests/admin.py | 4 +- tests/conftest.py | 10 ++-- tests/models.py | 5 ++ tests/settings.py | 2 + tests/test_admin.py | 6 +- tests/test_manager.py | 32 +++++----- tests/test_model.py | 44 +++++++------- tests/test_settings.py | 10 ++-- 18 files changed, 197 insertions(+), 93 deletions(-) diff --git a/README.md b/README.md index 69d724a..f552a74 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,9 @@ by enabling a cached backend. See [Advanced Usage](#advanced-usage) ## 4.0.0 (not released) - remove support for django 2.2 & 4.0 +- Bring your own PersistedTransition model: + From this relase, django-fsm-log is deprecating StateLog and instead encourages you + to define for your own application the concrete model that will persist the transition ## 3.1.0 (2023-03-23) @@ -99,14 +102,29 @@ python manage.py migrate django_fsm_log ## Usage +### Define you own model + +```python +from django_fsm_log.models import PersistedTransitionMixin + + +class TransitionLog(PersistedTransitionMixin): + pass +``` + +### Register the model + +```python +DJANGO_FSM_LOG_CONCRETE_MODEL = 'poll.models.TransitionLog' # This model must inherit from django_fsm_log.models.PersistedTransition +``` + The app listens for the `django_fsm.signals.post_transition` signal and creates a new record for each transition. To query the log: ```python -from django_fsm_log.models import StateLog -StateLog.objects.all() +TransitionLog.objects.all() # ...all recorded logs... ``` @@ -125,11 +143,10 @@ For convenience there is a custom `for_` manager method to easily filter on the ```python from my_app.models import Article -from django_fsm_log.models import StateLog article = Article.objects.all()[0] -StateLog.objects.for_(article) +TransitionLog.objects.for_(article) # ...logs for article... ``` @@ -157,7 +174,7 @@ With this the transition gets logged when the `by` kwarg is present. ```python article = Article.objects.create() -article.submit(by=some_user) # StateLog.by will be some_user +article.submit(by=some_user) # TransitionLog.by will be some_user ``` ### `description` Decorator @@ -210,21 +227,31 @@ article.submit() # logged with "Article submitted" description There is an InlineForm available that can be used to display the history of changes. -To use it expand your own `AdminModel` by adding `StateLogInline` to its inlines: +To use it expand your own `AdminModel` by adding `PersistedTransitionInline` to its inlines: ```python from django.contrib import admin -from django_fsm_log.admin import StateLogInline +from django_fsm_log.admin import PersistedTransitionInline @admin.register(FSMModel) class FSMModelAdmin(admin.ModelAdmin): - inlines = [StateLogInline] + inlines = [PersistedTransitionInline] +``` + +### Migration to Abstract model PersistedTransitionMixin + +Once you defined your own model, you'll have to create the relevant migration to create the table. + +```sh +python manage.py makemigrations ``` +Additionally you'd want to migrate the data from django_fsm_log.models.StateLog to your new table. + ### Advanced Usage -You can change the behaviour of this app by turning on caching for StateLog records. +You can change the behaviour of this app by turning on caching for PersistedTransition records. Simply add `DJANGO_FSM_LOG_STORAGE_METHOD = 'django_fsm_log.backends.CachedBackend'` to your project's settings file. It will use your project's default cache backend by default. If you wish to use a specific cache backend, you can add to your project's settings: @@ -233,22 +260,23 @@ your project's settings: DJANGO_FSM_LOG_CACHE_BACKEND = 'some_other_cache_backend' ``` -The StateLog object is now available after the `django_fsm.signals.pre_transition` +The PersistedTransition object is now available after the `django_fsm.signals.pre_transition` signal is fired, but is deleted from the cache and persisted to the database after `django_fsm.signals.post_transition` is fired. This is useful if: -- you need immediate access to StateLog details, and cannot wait until `django_fsm.signals.post_transition` +- you need immediate access to PersistedTransition details, and cannot wait until `django_fsm.signals.post_transition` has been fired -- at any stage, you need to verify whether or not the StateLog has been written to the database +- at any stage, you need to verify whether or not the PersistedTransition has been written to the database -Access to the pending StateLog record is available via the `pending_objects` manager +Access to the pending PersistedTransition record is available via the `pending_objects` manager ```python -from django_fsm_log.models import StateLog +from my_app.models import TransitionLog + article = Article.objects.get(...) -pending_state_log = StateLog.pending_objects.get_for_object(article) +pending_transition_logs = TransitionLog.pending_objects.get_for_object(article) ``` ## Contributing diff --git a/django_fsm_log/admin.py b/django_fsm_log/admin.py index 648e363..9acd9e6 100644 --- a/django_fsm_log/admin.py +++ b/django_fsm_log/admin.py @@ -1,13 +1,15 @@ +from warnings import warn + from django.contrib.contenttypes.admin import GenericTabularInline from django.db.models import F -from .models import StateLog +from .backends import _get_concrete_model -__all__ = ("StateLogInline",) +__all__ = ("PersistedTransitionInline",) -class StateLogInline(GenericTabularInline): - model = StateLog +class PersistedTransitionInline(GenericTabularInline): + model = _get_concrete_model() can_delete = False def has_add_permission(self, request, obj=None): @@ -30,3 +32,12 @@ def get_readonly_fields(self, request, obj=None): def get_queryset(self, request): return super().get_queryset(request).order_by(F("timestamp").desc()) + + +def StateLogInline(*args, **kwargs): + warn( + "StateLogInLine has been deprecated by PersistedTransitionInline.", + DeprecationWarning, + stacklevel=2, + ) + return PersistedTransitionInline(*args, **kwargs) diff --git a/django_fsm_log/apps.py b/django_fsm_log/apps.py index 50324ea..29d9417 100644 --- a/django_fsm_log/apps.py +++ b/django_fsm_log/apps.py @@ -10,9 +10,9 @@ class DjangoFSMLogAppConfig(AppConfig): def ready(self): backend = import_string(settings.DJANGO_FSM_LOG_STORAGE_METHOD) - StateLog = self.get_model("StateLog") + ConcreteModel = import_string(settings.DJANGO_FSM_LOG_CONCRETE_MODEL) - backend.setup_model(StateLog) + backend.setup_model(ConcreteModel) pre_transition.connect(backend.pre_transition_callback) post_transition.connect(backend.post_transition_callback) diff --git a/django_fsm_log/backends.py b/django_fsm_log/backends.py index 8b79964..e99840c 100644 --- a/django_fsm_log/backends.py +++ b/django_fsm_log/backends.py @@ -1,7 +1,18 @@ +import typing + +from django.utils.module_loading import import_string + from django_fsm_log.conf import settings from .helpers import FSMLogDescriptor +if typing.TYPE_CHECKING: + import django_fsm_log.models + + +def _get_concrete_model() -> typing.Type["django_fsm_log.models.PersistedTransitionMixin"]: + return import_string(settings.DJANGO_FSM_LOG_CONCRETE_MODEL) + def _pre_transition_callback(sender, instance, name, source, target, manager, **kwargs): if BaseBackend._get_model_qualified_name__(sender) in settings.DJANGO_FSM_LOG_IGNORED_MODELS: @@ -49,21 +60,21 @@ def _get_model_qualified_name__(sender): class CachedBackend(BaseBackend): @staticmethod def setup_model(model): - from .managers import PendingStateLogManager + from .managers import PendingPersistedTransitionManager - model.add_to_class("pending_objects", PendingStateLogManager()) + model.add_to_class("pending_objects", PendingPersistedTransitionManager()) @staticmethod def pre_transition_callback(sender, instance, name, source, target, **kwargs): - from .models import StateLog + klass = _get_concrete_model() - return _pre_transition_callback(sender, instance, name, source, target, StateLog.pending_objects, **kwargs) + return _pre_transition_callback(sender, instance, name, source, target, klass.pending_objects, **kwargs) @staticmethod def post_transition_callback(sender, instance, name, source, target, **kwargs): - from .models import StateLog + klass = _get_concrete_model() - StateLog.pending_objects.commit_for_object(instance) + klass.pending_objects.commit_for_object(instance) class SimpleBackend(BaseBackend): @@ -77,9 +88,9 @@ def pre_transition_callback(sender, **kwargs): @staticmethod def post_transition_callback(sender, instance, name, source, target, **kwargs): - from .models import StateLog + klass = _get_concrete_model() - return _pre_transition_callback(sender, instance, name, source, target, StateLog.objects, **kwargs) + return _pre_transition_callback(sender, instance, name, source, target, klass.objects, **kwargs) if settings.DJANGO_FSM_LOG_STORAGE_METHOD == "django_fsm_log.backends.CachedBackend": diff --git a/django_fsm_log/conf.py b/django_fsm_log/conf.py index 144df77..37f7cdb 100644 --- a/django_fsm_log/conf.py +++ b/django_fsm_log/conf.py @@ -1,3 +1,5 @@ +from typing import List + from appconf import AppConf from django.conf import settings # noqa: F401 @@ -5,4 +7,9 @@ class DjangoFSMLogConf(AppConf): STORAGE_METHOD = "django_fsm_log.backends.SimpleBackend" CACHE_BACKEND = "default" - IGNORED_MODELS = [] + IGNORED_MODELS: List[str] = [] + CONCRETE_MODEL: str = "django_fsm_log.models.StateLog" + + class Meta: + prefix = "django_fsm_log" + holder = "django_fsm_log.conf.settings" diff --git a/django_fsm_log/managers.py b/django_fsm_log/managers.py index d3fd057..c3c238c 100644 --- a/django_fsm_log/managers.py +++ b/django_fsm_log/managers.py @@ -1,3 +1,5 @@ +from warnings import warn + from django.contrib.contenttypes.models import ContentType from django.db import models from django.db.models.query import QuerySet @@ -5,7 +7,7 @@ from django_fsm_log.backends import cache -class StateLogQuerySet(QuerySet): +class PersistedTransitionQuerySet(QuerySet): def _get_content_type(self, obj): return ContentType.objects.get_for_model(obj) @@ -13,11 +15,16 @@ def for_(self, obj): return self.filter(content_type=self._get_content_type(obj), object_id=obj.pk) -class StateLogManager(models.Manager): +def StateLogQuerySet(*args, **kwargs): + warn("StateLogQuerySet has been renamed PersistedTransitionQuerySet", DeprecationWarning, stacklevel=2) + return PersistedTransitionQuerySet(*args, **kwargs) + + +class PersistedTransitionManager(models.Manager): use_in_migrations = True def get_queryset(self): - return StateLogQuerySet(self.model) + return PersistedTransitionQuerySet(self.model) def __getattr__(self, attr, *args): # see https://code.djangoproject.com/ticket/15062 for details @@ -26,7 +33,12 @@ def __getattr__(self, attr, *args): return getattr(self.get_queryset(), attr, *args) -class PendingStateLogManager(models.Manager): +def StateLogManager(*args, **kwargs): + warn("StateLogManager has been renamed PersistedTransitionManager", DeprecationWarning, stacklevel=2) + return PersistedTransitionManager(*args, **kwargs) + + +class PendingPersistedTransitionManager(models.Manager): def _get_cache_key_for_object(self, obj): return f"StateLog:{obj.__class__.__name__}:{obj.pk}" @@ -46,3 +58,8 @@ def commit_for_object(self, obj): def get_for_object(self, obj): key = self._get_cache_key_for_object(obj) return cache.get(key) + + +def PendingStateLogManager(*args, **kwargs): + warn("PendingStateLogManager has been renamed PendingPersistedTransitionManager", DeprecationWarning, stacklevel=2) + return PendingPersistedTransitionManager(*args, **kwargs) diff --git a/django_fsm_log/migrations/0001_initial.py b/django_fsm_log/migrations/0001_initial.py index 933e877..f7a2bc0 100644 --- a/django_fsm_log/migrations/0001_initial.py +++ b/django_fsm_log/migrations/0001_initial.py @@ -1,6 +1,6 @@ -from django.db import models, migrations import django.utils.timezone from django.conf import settings +from django.db import migrations, models class Migration(migrations.Migration): diff --git a/django_fsm_log/migrations/0004_auto_20190131_0341.py b/django_fsm_log/migrations/0004_auto_20190131_0341.py index 5e65275..9fdce93 100644 --- a/django_fsm_log/migrations/0004_auto_20190131_0341.py +++ b/django_fsm_log/migrations/0004_auto_20190131_0341.py @@ -1,6 +1,7 @@ # Generated by Django 2.1.5 on 2019-01-31 03:41 from django.db import migrations + import django_fsm_log.managers diff --git a/django_fsm_log/models.py b/django_fsm_log/models.py index fc13d8e..6078025 100644 --- a/django_fsm_log/models.py +++ b/django_fsm_log/models.py @@ -1,14 +1,22 @@ +from warnings import warn + +from django.conf import settings from django.contrib.contenttypes.fields import GenericForeignKey from django.contrib.contenttypes.models import ContentType from django.db import models from django.utils.timezone import now from django_fsm import FSMFieldMixin, FSMIntegerField -from .conf import settings -from .managers import StateLogManager +from .managers import PersistedTransitionManager + +class PersistedTransitionMixin(models.Model): + """ + Abstract Class that should be subclassed by the host application. + Host projects should own the migrations and + can decide on their own primary key type. + """ -class StateLog(models.Model): timestamp = models.DateTimeField(default=now) by = models.ForeignKey( getattr(settings, "AUTH_USER_MODEL", "auth.User"), @@ -26,9 +34,10 @@ class StateLog(models.Model): description = models.TextField(blank=True, null=True) - objects = StateLogManager() + objects = PersistedTransitionManager() class Meta: + abstract = True get_latest_by = "timestamp" def __str__(self): @@ -47,3 +56,14 @@ def get_state_display(self, field_name="state"): def get_source_state_display(self): return self.get_state_display("source_state") + + +class StateLog(PersistedTransitionMixin): + def __init_subclass__(cls): + warn( + "StateLog model has been deprecated, you should now bring your own Model." + "\nPlease check the documentation at https://django-fsm-log.readthedocs.io/en/latest/" + "\nto know how to.", + DeprecationWarning, + stacklevel=2, + ) diff --git a/pyproject.toml b/pyproject.toml index ee03ee7..d933e7c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,10 +1,10 @@ [tool.black] line-length = 119 -target-version = ["py311"] +target-version = ["py37"] extend-exclude = "(^/django_fsm_log/migrations/.*$|^docs/.*$)" [tool.ruff] line-length = 119 -target-version = "py311" +target-version = "py37" select = ["E", "F", "I", "B", "C4", "T20", "TID", "UP"] exclude = ["django_fsm_log/migrations", ".tox", "build"] diff --git a/tests/admin.py b/tests/admin.py index ec0c9de..39677a7 100644 --- a/tests/admin.py +++ b/tests/admin.py @@ -1,12 +1,12 @@ from django.contrib import admin -from django_fsm_log.admin import StateLogInline +from django_fsm_log.admin import PersistedTransitionInline from .models import Article class ArticleAdmin(admin.ModelAdmin): - inlines = [StateLogInline] + inlines = [PersistedTransitionInline] admin.site.register(Article, ArticleAdmin) diff --git a/tests/conftest.py b/tests/conftest.py index 36f19b2..4515383 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,8 +1,9 @@ import pytest from django.contrib.auth import get_user_model +from django.utils.module_loading import import_string -from django_fsm_log.managers import PendingStateLogManager -from django_fsm_log.models import StateLog +from django_fsm_log.conf import settings +from django_fsm_log.managers import PendingPersistedTransitionManager from .models import Article, ArticleInteger @@ -33,5 +34,6 @@ def user(db): @pytest.fixture(autouse=True) def pending_objects(db, request): if "pending_objects" in request.keywords: - if not hasattr(StateLog, "pending_objects"): - StateLog.add_to_class("pending_objects", PendingStateLogManager()) + model_class = import_string(settings.DJANGO_FSM_LOG_CONCRETE_MODEL) + if not hasattr(model_class, "pending_objects"): + model_class.add_to_class("pending_objects", PendingPersistedTransitionManager()) diff --git a/tests/models.py b/tests/models.py index 2a1698b..44c7473 100644 --- a/tests/models.py +++ b/tests/models.py @@ -2,6 +2,11 @@ from django_fsm import FSMField, FSMIntegerField, transition from django_fsm_log.decorators import fsm_log_by, fsm_log_description +from django_fsm_log.models import PersistedTransitionMixin + + +class PersistedTransition(PersistedTransitionMixin): + pass class Article(models.Model): diff --git a/tests/settings.py b/tests/settings.py index 1878b10..ae2f07e 100644 --- a/tests/settings.py +++ b/tests/settings.py @@ -34,3 +34,5 @@ ] USE_TZ = True + +DJANGO_FSM_LOG_CONCRETE_MODEL = "tests.models.PersistedTransition" diff --git a/tests/test_admin.py b/tests/test_admin.py index 70c8b5e..793598a 100644 --- a/tests/test_admin.py +++ b/tests/test_admin.py @@ -1,8 +1,4 @@ -try: - from django.urls import reverse -except ImportError: - # django<=1.10 - from django.core.urlresolvers import reverse +from django.urls import reverse def test_state_log_inline_django2(article, admin_client, admin_user): diff --git a/tests/test_manager.py b/tests/test_manager.py index 33f107a..7aa4d33 100644 --- a/tests/test_manager.py +++ b/tests/test_manager.py @@ -1,6 +1,8 @@ import pytest -from django_fsm_log.models import StateLog +from django_fsm_log.backends import _get_concrete_model + +ConcreteModel = _get_concrete_model() def test_for_queryset_method_returns_only_logs_for_provided_object(article, article2): @@ -9,8 +11,8 @@ def test_for_queryset_method_returns_only_logs_for_provided_object(article, arti article.submit() article.publish() - assert len(StateLog.objects.for_(article)) == 2 - for log in StateLog.objects.for_(article): + assert len(ConcreteModel.objects.for_(article)) == 2 + for log in ConcreteModel.objects.for_(article): assert article == log.content_object @@ -27,15 +29,15 @@ def create_kwargs(user, article): @pytest.mark.pending_objects def test_get_cache_key_for_object_returns_correctly_formatted_string(article): expected_result = f"StateLog:{article.__class__.__name__}:{article.pk}" - result = StateLog.pending_objects._get_cache_key_for_object(article) + result = ConcreteModel.pending_objects._get_cache_key_for_object(article) assert result == expected_result @pytest.mark.pending_objects def test_create_pending_sets_cache_item(article, create_kwargs, mocker): mock_cache = mocker.patch("django_fsm_log.managers.cache") - expected_cache_key = StateLog.pending_objects._get_cache_key_for_object(article) - StateLog.pending_objects.create(**create_kwargs) + expected_cache_key = ConcreteModel.pending_objects._get_cache_key_for_object(article) + ConcreteModel.pending_objects.create(**create_kwargs) cache_key = mock_cache.set.call_args_list[0][0][0] cache_object = mock_cache.set.call_args_list[0][0][1] assert cache_key == expected_cache_key @@ -48,7 +50,7 @@ def test_create_pending_sets_cache_item(article, create_kwargs, mocker): @pytest.mark.pending_objects def test_create_returns_correct_state_log(mocker, create_kwargs): mocker.patch("django_fsm_log.managers.cache") - log = StateLog.pending_objects.create(**create_kwargs) + log = ConcreteModel.pending_objects.create(**create_kwargs) assert log.state == create_kwargs["state"] assert log.transition == create_kwargs["transition"] assert log.content_object == create_kwargs["content_object"] @@ -58,10 +60,10 @@ def test_create_returns_correct_state_log(mocker, create_kwargs): @pytest.mark.pending_objects def test_commit_for_object_saves_log(mocker, article, create_kwargs): mock_cache = mocker.patch("django_fsm_log.managers.cache") - log = StateLog.objects.create(**create_kwargs) + log = ConcreteModel.objects.create(**create_kwargs) mock_cache.get.return_value = log - StateLog.pending_objects.commit_for_object(article) - persisted_log = StateLog.objects.order_by("-pk").all()[0] + ConcreteModel.pending_objects.commit_for_object(article) + persisted_log = ConcreteModel.objects.order_by("-pk").all()[0] assert log.state == persisted_log.state assert log.transition == persisted_log.transition assert log.content_object == persisted_log.content_object @@ -71,14 +73,14 @@ def test_commit_for_object_saves_log(mocker, article, create_kwargs): @pytest.mark.pending_objects def test_commit_for_object_deletes_pending_log_from_cache(mocker, article, create_kwargs): mock_cache = mocker.patch("django_fsm_log.managers.cache") - StateLog.pending_objects.create(**create_kwargs) - StateLog.pending_objects.commit_for_object(article) - mock_cache.delete.assert_called_once_with(StateLog.pending_objects._get_cache_key_for_object(article)) + ConcreteModel.pending_objects.create(**create_kwargs) + ConcreteModel.pending_objects.commit_for_object(article) + mock_cache.delete.assert_called_once_with(ConcreteModel.pending_objects._get_cache_key_for_object(article)) @pytest.mark.pending_objects def test_get_for_object_calls_cache_get_with_correct_key(mocker, create_kwargs): mock_cache = mocker.patch("django_fsm_log.managers.cache") - cache_key = StateLog.pending_objects._get_cache_key_for_object(create_kwargs["content_object"]) - StateLog.pending_objects.get_for_object(create_kwargs["content_object"]) + cache_key = ConcreteModel.pending_objects._get_cache_key_for_object(create_kwargs["content_object"]) + ConcreteModel.pending_objects.get_for_object(create_kwargs["content_object"]) mock_cache.get.assert_called_once_with(cache_key) diff --git a/tests/test_model.py b/tests/test_model.py index 586c210..f7b560c 100644 --- a/tests/test_model.py +++ b/tests/test_model.py @@ -1,10 +1,12 @@ import pytest from django_fsm import TransitionNotAllowed -from django_fsm_log.models import StateLog +from django_fsm_log.backends import _get_concrete_model from .models import Article, ArticleInteger +ConcreteModel = _get_concrete_model() + def test_get_available_state_transitions(article): assert len(list(article.get_available_state_transitions())) == 5 @@ -15,35 +17,35 @@ def test_get_all_state_transitions(article): def test_log_created_on_transition(article): - assert len(StateLog.objects.all()) == 0 + assert len(ConcreteModel.objects.all()) == 0 article.submit() article.save() - assert len(StateLog.objects.all()) == 1 + assert len(ConcreteModel.objects.all()) == 1 def test_log_not_created_if_transition_fails(article): - assert len(StateLog.objects.all()) == 0 + assert len(ConcreteModel.objects.all()) == 0 with pytest.raises(TransitionNotAllowed): article.publish() - assert len(StateLog.objects.all()) == 0 + assert len(ConcreteModel.objects.all()) == 0 def test_log_not_created_if_target_is_none(article): - assert len(StateLog.objects.all()) == 0 + assert len(ConcreteModel.objects.all()) == 0 article.validate_draft() - assert len(StateLog.objects.all()) == 0 + assert len(ConcreteModel.objects.all()) == 0 def test_by_is_set_when_passed_into_transition(article, user): article.submit(by=user) - log = StateLog.objects.all()[0] + log = ConcreteModel.objects.all()[0] assert user == log.by with pytest.raises(AttributeError): article.__django_fsm_log_attr_by @@ -52,7 +54,7 @@ def test_by_is_set_when_passed_into_transition(article, user): def test_by_is_none_when_not_set_in_transition(article): article.submit() - log = StateLog.objects.all()[0] + log = ConcreteModel.objects.all()[0] assert log.by is None @@ -60,7 +62,7 @@ def test_description_is_set_when_passed_into_transition(article): description = "Lorem ipsum" article.submit(description=description) - log = StateLog.objects.all()[0] + log = ConcreteModel.objects.all()[0] assert description == log.description with pytest.raises(AttributeError): article.__django_fsm_log_attr_description @@ -69,7 +71,7 @@ def test_description_is_set_when_passed_into_transition(article): def test_description_is_none_when_not_set_in_transition(article): article.submit() - log = StateLog.objects.all()[0] + log = ConcreteModel.objects.all()[0] assert log.description is None @@ -77,7 +79,7 @@ def test_description_can_be_mutated_by_the_transition(article): description = "Sed egestas dui" article.submit_inline_description_change(change_to=description) - log = StateLog.objects.all()[0] + log = ConcreteModel.objects.all()[0] assert description == log.description with pytest.raises(AttributeError): article.__django_fsm_log_attr_description @@ -89,7 +91,7 @@ def test_default_description(article): article.restore() article.save() - log = StateLog.objects.all()[1] + log = ConcreteModel.objects.all()[1] assert log.description == "Article restored" @@ -99,7 +101,7 @@ def test_default_description_call_priority(article): article.restore(description="Restored because of mistake") article.save() - log = StateLog.objects.all()[1] + log = ConcreteModel.objects.all()[1] assert log.description == "Restored because of mistake" @@ -107,28 +109,28 @@ def test_default_description_inline_priority(article): article.publish_as_temporary() article.save() - log = StateLog.objects.all()[0] + log = ConcreteModel.objects.all()[0] assert log.description == "Article published (temporary)" def test_logged_state_is_new_state(article): article.submit() - log = StateLog.objects.all()[0] + log = ConcreteModel.objects.all()[0] assert log.state == "submitted" def test_logged_transition_is_name_of_transition_method(article): article.submit() - log = StateLog.objects.all()[0] + log = ConcreteModel.objects.all()[0] assert log.transition == "submit" def test_logged_content_object_is_instance_being_transitioned(article): article.submit() - log = StateLog.objects.all()[0] + log = ConcreteModel.objects.all()[0] assert log.content_object == article @@ -136,7 +138,7 @@ def test_get_display_state(article): article.submit() article.save() - log = StateLog.objects.latest() + log = ConcreteModel.objects.latest() article = Article.objects.get(pk=article.pk) prev_state = article.get_state_display() @@ -145,7 +147,7 @@ def test_get_display_state(article): article.publish() article.save() - log = StateLog.objects.latest() + log = ConcreteModel.objects.latest() article = Article.objects.get(pk=article.pk) @@ -157,7 +159,7 @@ def test_get_display_state_with_integer(article_integer): article_integer.change_to_two() article_integer.save() - log = StateLog.objects.latest() + log = ConcreteModel.objects.latest() article_integer = ArticleInteger.objects.get(pk=article_integer.pk) assert log.get_state_display() == article_integer.get_state_display() diff --git a/tests/test_settings.py b/tests/test_settings.py index 1373fcb..b275433 100644 --- a/tests/test_settings.py +++ b/tests/test_settings.py @@ -1,25 +1,25 @@ import pytest from django.conf import settings -from django_fsm_log.models import StateLog +from tests.models import PersistedTransition pytestmark = pytest.mark.ignore_article def test_log_not_created_if_model_ignored(article): - assert len(StateLog.objects.all()) == 0 + assert len(PersistedTransition.objects.all()) == 0 article.submit() article.save() - assert len(StateLog.objects.all()) == 0 + assert len(PersistedTransition.objects.all()) == 0 def test_log_created_on_transition_when_model_not_ignored(article): settings.DJANGO_FSM_LOG_IGNORED_MODELS = ["tests.models.SomeOtherModel"] - assert len(StateLog.objects.all()) == 0 + assert len(PersistedTransition.objects.all()) == 0 article.submit() article.save() - assert len(StateLog.objects.all()) == 1 + assert len(PersistedTransition.objects.all()) == 1