From 938ea36e305e36b88ddfc78751f627894ff9d395 Mon Sep 17 00:00:00 2001 From: Ashu Goel Date: Mon, 21 Jun 2021 18:35:50 -0700 Subject: [PATCH 1/3] pass in parent_obj when fetching inline_instances Some ModelAdmin pages depend on the object itself existing and some properties of the object in order to display inlines. We should make sure we pass in the proper object when fetching inline instances in order to determine which action to use. --- inline_actions/admin.py | 2 +- test_proj/blog/admin.py | 13 +++++++- test_proj/blog/models.py | 5 +++ test_proj/blog/tests/test_inline_admin.py | 37 +++++++++++++++++++++++ 4 files changed, 55 insertions(+), 2 deletions(-) diff --git a/inline_actions/admin.py b/inline_actions/admin.py index 4d0f6e8..5b57ea5 100755 --- a/inline_actions/admin.py +++ b/inline_actions/admin.py @@ -254,7 +254,7 @@ def _handle_action(self, request, object_id=None): # parent_obj is None because `object_id` is None else: - for inline in self.get_inline_instances(request): + for inline in self.get_inline_instances(request, obj=parent_obj): inline_class_name = inline.__class__.__name__.lower() matches_inline_class = inline_class_name == admin_class_name matches_model = inline.model == model diff --git a/test_proj/blog/admin.py b/test_proj/blog/admin.py index 36480ca..5d9199e 100755 --- a/test_proj/blog/admin.py +++ b/test_proj/blog/admin.py @@ -6,7 +6,7 @@ from inline_actions.admin import InlineActionsMixin, InlineActionsModelAdminMixin from . import forms -from .models import Article, Author, AuthorProxy +from .models import Article, Author, AuthorProxy, AuthorSecondProxy class UnPublishActionsMixin(object): @@ -138,6 +138,17 @@ class AuthorAdmin(InlineActionsModelAdminMixin, admin.ModelAdmin): inline_actions = None +@admin.register(AuthorSecondProxy) +class AuthorMaybeInlineAdmin(InlineActionsModelAdminMixin, admin.ModelAdmin): + list_display = ('name',) + inline_actions = None + + def get_inlines(self, request, obj): + if not obj or obj.name != 'DISPLAY INLINE': + return [] + return [ArticleInline] + + @admin.register(Article) class ArticleAdmin( UnPublishActionsMixin, diff --git a/test_proj/blog/models.py b/test_proj/blog/models.py index 2514e9d..2a28e80 100644 --- a/test_proj/blog/models.py +++ b/test_proj/blog/models.py @@ -38,3 +38,8 @@ def __str__(self): class AuthorProxy(Author): class Meta: proxy = True + + +class AuthorSecondProxy(Author): + class Meta: + proxy = True diff --git a/test_proj/blog/tests/test_inline_admin.py b/test_proj/blog/tests/test_inline_admin.py index 9a0c932..c1567c3 100644 --- a/test_proj/blog/tests/test_inline_admin.py +++ b/test_proj/blog/tests/test_inline_admin.py @@ -156,6 +156,43 @@ def test_publish_action(admin_client, mocker, article): assert article.status == Article.DRAFT +def test_publish_action_works_with_dynamic_inlines( + admin_client, mocker, author, article +): + """ + Tests whether we can execute an inline action if the inline class is dynamically displayed. + """ + from ..admin import UnPublishActionsMixin + + author.name = 'DISPLAY INLINE' + author.save() + + mocker.spy(UnPublishActionsMixin, 'get_inline_actions') + mocker.spy(UnPublishActionsMixin, 'publish') + mocker.spy(UnPublishActionsMixin, 'unpublish') + assert article.status == Article.DRAFT + + publish_input_name = ( + '_action__articleinline__inline__publish__blog__article__{}'.format(article.pk) + ) + unpublish_input_name = ( + '_action__articleinline__inline__unpublish__blog__article__{}'.format( + article.pk + ) + ) + author_url = reverse('admin:blog_authorsecondproxy_change', args=(author.pk,)) + changeview = admin_client.get(author_url) + assert UnPublishActionsMixin.get_inline_actions.call_count > 0 + assert publish_input_name in dict(changeview.form.fields) + # execute and test publish action + changeview = changeview.form.submit(name=publish_input_name).follow() + article = Article.objects.get(pk=article.pk) + assert publish_input_name not in dict(changeview.form.fields) + assert unpublish_input_name in dict(changeview.form.fields) + assert UnPublishActionsMixin.publish.call_count == 1 + assert article.status == Article.PUBLISHED + + def test_view_action(admin_client, mocker, article): """Test view action.""" from inline_actions.actions import ViewAction From 5d32e91e3448c41d389e96159b425f1fadd49e8b Mon Sep 17 00:00:00 2001 From: Ashu Goel Date: Mon, 21 Jun 2021 18:53:46 -0700 Subject: [PATCH 2/3] update contributors --- CONTRIBUTORS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index e468005..1abc00a 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -9,3 +9,4 @@ - [@tony](https://github.com/tony) - [@tripliks](https://github.com/tripliks) - [@Ivan-Feofanov](https://github.com/Ivan-Feofanov) +- [@asgoel](https://github.com/asgoel) From 70330f271bb3f2668dcb9c010b7557fb585ac3a4 Mon Sep 17 00:00:00 2001 From: Ashu Goel Date: Fri, 21 Jan 2022 15:12:38 -0800 Subject: [PATCH 3/3] udpate changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) mode change 100644 => 100755 CHANGELOG.md diff --git a/CHANGELOG.md b/CHANGELOG.md old mode 100644 new mode 100755 index 9454168..4a817bb --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed * removed RemovedInDjango40Warning warning message, thanks to @Ivan-Feofanov +* fixed a bug where the handle_action function does not pass through parent objects into `get_inline_instances` ## [2.4.0] - 2021-02-08