-
Notifications
You must be signed in to change notification settings - Fork 24
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #51 from akodelia/feature/LITE-21102-New-mixin-to-…
…allow-sync-items-from-django-admin-site Mixin to add cqrs sync action on Django Admin
- Loading branch information
Showing
6 changed files
with
174 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
# Copyright © 2021 Ingram Micro Inc. All rights reserved. | ||
|
||
from django.utils.translation import gettext_lazy | ||
|
||
|
||
class CQRSAdminMasterSyncMixin: | ||
""" | ||
Mixin that includes a custom action in AdminModel. This action allows synchronizing | ||
master's model items from Django Admin page, | ||
""" | ||
|
||
def get_actions(self, request): | ||
""" | ||
Overriding method from AdminModel class; it is used to include the sync method in | ||
the actions list. | ||
""" | ||
if self.actions is not None: | ||
self.actions = self.actions + ['sync_items'] | ||
return super().get_actions(request) | ||
|
||
def _cqrs_sync_queryset(self, queryset): | ||
""" | ||
This function is used to adjust the QuerySet before sending the sync signal. | ||
:param queryset: Original queryset | ||
:type queryset: Queryset | ||
:return: Updated queryset | ||
:rtype: Queryset | ||
""" | ||
return queryset | ||
|
||
def sync_items(self, request, queryset): | ||
""" | ||
This method synchronizes selected items from the Admin Page. | ||
It is registered as a custom action in Django Admin | ||
""" | ||
items_not_synced = [] | ||
for item in self._cqrs_sync_queryset(queryset): | ||
if not item.cqrs_sync(): | ||
items_not_synced.append(item) | ||
|
||
total = len(queryset) | ||
total_w_erros = len(items_not_synced) | ||
total_sucess = total - total_w_erros | ||
self.message_user( | ||
request, | ||
f'{total_sucess} successfully synced. {total_w_erros} failed: {items_not_synced}', | ||
) | ||
|
||
sync_items.short_description = gettext_lazy( | ||
'Synchronize selected %(verbose_name_plural)s via CQRS', | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
Django Admin | ||
==================== | ||
|
||
Synchronize items | ||
----------------- | ||
|
||
Add action to synchronize master items from Django Admin page. | ||
|
||
.. code-block:: python | ||
from django.db import models | ||
from django.contrib import admin | ||
from dj_cqrs.admin_mixins import CQRSAdminMasterSyncMixin | ||
class AccountAdmin(CQRSAdminMasterSyncMixin, admin.ModelAdmin): | ||
pass | ||
admin.site.register(models.Account, AccountAdmin) | ||
* If necessary, override ``_cqrs_sync_queryset`` from ``CQRSAdminMasterSyncMixin`` to adjust the QuerySet and use it for synchronization. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
# Copyright © 2021 Ingram Micro Inc. All rights reserved. | ||
|
||
from dj_cqrs.admin import CQRSAdminMasterSyncMixin | ||
|
||
from django.contrib import admin | ||
|
||
import pytest | ||
|
||
|
||
class MockAdminModel(CQRSAdminMasterSyncMixin, admin.ModelAdmin): | ||
pass | ||
|
||
|
||
@pytest.mark.parametrize( | ||
('total_sync', 'total_failed'), | ||
( | ||
(2, 1), | ||
(3, 0), | ||
(0, 3), | ||
(0, 0), | ||
), | ||
) | ||
def test_sync_items_function(total_sync, total_failed, mocker): | ||
model_path = 'dj_cqrs.mixins.MasterMixin' | ||
mock_model = mocker.patch(model_path) | ||
request = None | ||
|
||
qs = [] | ||
for _ in range(total_sync): | ||
m = mocker.patch(model_path) | ||
m.cqrs_sync.return_value = True | ||
qs.append(m) | ||
|
||
failed_items = [] | ||
for _ in range(total_failed): | ||
m = mocker.patch(model_path) | ||
m.cqrs_sync.return_value = False | ||
qs.append(m) | ||
failed_items.append(m) | ||
|
||
mixin = MockAdminModel(model=mock_model, admin_site=admin.sites.AdminSite()) | ||
mixin.message_user = mocker.Mock() | ||
mixin.sync_items(request, qs) | ||
|
||
mixin.message_user.assert_called_once_with( | ||
request, | ||
f'{total_sync} successfully synced. {total_failed} failed: {failed_items}', | ||
) | ||
|
||
|
||
def test_admin_actions_enabled_with_sync_items_action(mocker): | ||
mock_model = mocker.Mock() | ||
request = mocker.patch('django.http.HttpRequest') | ||
mixin = MockAdminModel(model=mock_model, admin_site=admin.sites.AdminSite()) | ||
actions = mixin.get_actions(request) | ||
|
||
assert 'sync_items' in actions | ||
assert 'delete_selected' in actions | ||
|
||
|
||
def test_actions_not_enabled(mocker): | ||
mock_model = mocker.Mock() | ||
request = mocker.patch('django.http.HttpRequest') | ||
mixin = MockAdminModel(model=mock_model, admin_site=admin.sites.AdminSite()) | ||
mixin.actions = None | ||
actions = mixin.get_actions(request) | ||
|
||
assert actions == {} |