Skip to content

Instantly share code, notes, and snippets.

@thibaut-pro
Forked from rafen/README.md
Last active June 5, 2020 23:29
Show Gist options
  • Save thibaut-pro/663df42026df103dd20530a338f6c297 to your computer and use it in GitHub Desktop.
Save thibaut-pro/663df42026df103dd20530a338f6c297 to your computer and use it in GitHub Desktop.
Django ExtendedActionsMixin allows ModelAdmin classes to execute actions with empty queryset and filtered queryset

ExtendedActionsMixin

This is a Django mixin that allows ModelAdmin classes to execute actions without selecting any objects on the change list of the Django Admin.

To implement it you need to include the Mixin as usual (see https://docs.djangoproject.com/en/1.10/topics/class-based-views/mixins/) and define a class attribute called extended_actions containing a list of string with the name of the actions that you want to be exectued with empty queryset.

If in the action you want to use the same queryset that the user is seeing, you can use the get_filtered_queryset method also provided by the mixin

Example:

@admin.register(Contact)
class ContactAdmin(ExtendedActionsMixin, admin.ModelAdmin):
    list_display = ('name', 'country', 'state')
    actions = ('export',)
    extended_actions = ('export',)
    
    def export(self, request, queryset):
        if not queryset:
            # if not queryset use the queryset filtered by the URL parameters
            queryset = self.get_filtered_queryset(request)

        # As usual do something with the queryset
class ExtendedActionsMixin(object):
# actions that can be executed with no items selected on the admin change list.
# The filtered queryset displayed to the user will be used instead
extended_actions = []
def changelist_view(self, request, extra_context=None):
# if a extended action is called and there's no checkbox selected, select one with
# invalid id, to get an empty queryset
if 'action' in request.POST and request.POST['action'] in self.extended_actions:
if not request.POST.getlist(admin.helpers.ACTION_CHECKBOX_NAME):
post = request.POST.copy()
post.update({admin.helpers.ACTION_CHECKBOX_NAME: 0})
request._set_post(post)
return super(ExtendedActionsMixin, self).changelist_view(request, extra_context)
def get_changelist_instance(self, request):
"""
Returns a simple ChangeList view instance of the current ModelView.
(It's a simple instance since we don't populate the actions and list filter
as expected since those are not used by this class)
"""
list_display = self.get_list_display(request)
list_display_links = self.get_list_display_links(request, list_display)
list_filter = self.get_list_filter(request)
search_fields = self.get_search_fields(request)
list_select_related = self.get_list_select_related(request)
ChangeList = self.get_changelist(request)
return ChangeList(
request, self.model, list_display,
list_display_links, list_filter, self.date_hierarchy,
search_fields, list_select_related, self.list_per_page,
self.list_max_show_all, self.list_editable, self,
)
def get_filtered_queryset(self, request):
"""
Returns a queryset filtered by the URLs parameters
"""
cl = self.get_changelist_instance(request)
return cl.get_queryset(request)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment