#37265 assigned Bug

Admin crashes when ModelAdmin.get_action() or get_action_choices() are overridden with their pre-6.1 signatures

Reported by: Adam Johnson Owned by: Adam Johnson
Component: contrib.admin Version: 6.1
Severity: Release blocker Keywords:
Cc: Triage Stage: Unreviewed
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

Django 6.1 crashes with a 500 on every admin page that uses actions (and even during system checks) for projects that override ModelAdmin.get_action() or ModelAdmin.get_action_choices() with their documented pre-6.1 signatures.

Here’s a minimal reproduction that works on Django 6.0, but crashes on 6.1 and main:

from django.contrib import admin
from django.db.models import BLANK_CHOICE_DASH

@admin.register(MyModel)
class MyModelAdmin(admin.ModelAdmin):
    actions = ["my_action"]

    # (1) TypeError: get_action() takes 2 positional arguments but 3 were given
    #     Raised by system checks and by any changelist/change form request.
    def get_action(self, action):
        return super().get_action(action)

    # (2) TypeError: get_action_choices() got an unexpected keyword argument 'default_choices'
    def get_action_choices(self, request):
        return super().get_action_choices(request)

    # (2b) Or, with the old default: TypeError: 'NoneType' object is not iterable
    # def get_action_choices(self, request, default_choices=BLANK_CHOICE_DASH):
    #     return [*default_choices, ...]

    @admin.action(description="My action")
    def my_action(self, request, queryset):
        ...

Regression in f30acb184f75fd9260cfd6ddc48a3bbbd49f9c1d (Fixed #12090 -- Added admin actions to the admin change form), interacting with 63c56cda1 (blank-choice default changed to None):

  • ModelAdmin._get_base_actions() now calls self.get_action(action, action_location) with two arguments and there is no deprecation shim at all for old-signature get_action() overrides — they raise TypeError immediately, including from ModelAdminChecks._check_actions(), so manage.py check fails too. Overrides returning the old (callable, name, description) tuple additionally break downstream action.name/action.func attribute access on the new Action dataclass.
  • The get_action_choices() shim (_get_action_choices_with_action_location()) exists, but always calls self.get_action_choices(request, default_choices=default_choices) with default_choices=None: overrides without the parameter get an unexpected keyword argument, and overrides keeping the old default_choices=BLANK_CHOICE_DASH default receive an explicit None instead of their signature default (in 6.0 Django called get_action_choices(request) with no extra arguments).

Change History (0)

Note: See TracTickets for help on using tickets.
Back to Top