django admin动作而不选择对象

问题描述 投票:0回答:7

可以为django管理员创建自定义的管理员操作,该操作不需要选择某些对象以运行它?

如果您尝试在不选择对象的情况下进行操作,则会收到消息:

Items must be selected in order to perform actions on them. No items have been changed.

有一种方法可以覆盖这种行为并让动作运行吗?

django django-admin
7个回答
33
投票

在Django 1.6中,接受的答案对我不起作用,所以我最终得到了:

from django.contrib import admin
from django.contrib.admin.helpers import ACTION_CHECKBOX_NAME

class MyModelAdmin(admin.ModelAdmin):

    ....

    def changelist_view(self, request, extra_context=None):
        if 'action' in request.POST and request.POST['action'] == 'your_action_here':
            if not request.POST.getlist(ACTION_CHECKBOX_NAME):
                post = request.POST.copy()
                for u in MyModel.objects.all():
                    post.update({ACTION_CHECKBOX_NAME: str(u.id)})
                request._set_post(post)
        return super(MyModelAdmin, self).changelist_view(request, extra_context)

当调用并未选择任何选择时,请选择db中的所有实例。


我想要这个,但最终决定不使用它。在此处发布以备将来参考。

添加了额外的属性(例如

my_action

13
投票

MyModel


在您的
acts_on_all

中,覆盖
def my_action(modeladmin, request, queryset):
    pass
my_action.short_description = "Act on all %(verbose_name_plural)s"
my_action.acts_on_all = True
检查您的财产。

如果请求方法是发布的,并且有一个指定的操作,并且该操作可COLLABLE将您的属性设置为true,请修改代表选定对象的列表。

ModelAdmin


Yuji在正确的轨道上,但是我使用了一个可能对您有用的简单解决方案。  如果您按照下面完成的效率响应_action,则可以在检查发生之前,用包含所有对象的QuerySet替换空QuerySet。  该代码还检查您正在运行的操作以确保其在更改QuerySet之前已批准在所有对象上运行,因此您可以将其限制在某些情况下。  
changelist_view

  
有一种方法可以覆盖这个 行为并让动作运行 无论如何?

7
投票
我要说的不,没有简单的方法。

如果您抓取错误消息,则看到代码在

def changelist_view(self, request, extra_context=None): try: action = self.get_actions(request)[request.POST['action']][0] action_acts_on_all = action.acts_on_all except (KeyError, AttributeError): action_acts_on_all = False if action_acts_on_all: post = request.POST.copy() post.setlist(admin.helpers.ACTION_CHECKBOX_NAME, self.model.objects.values_list('id', flat=True)) request.POST = post return admin.ModelAdmin.changelist_view(self, request, extra_context)
中,问题代码在changelist_view中深处。

def response_action(self, request, queryset): # override to allow for exporting of ALL records to CSV if no chkbox selected selected = request.POST.getlist(admin.ACTION_CHECKBOX_NAME) if request.META['QUERY_STRING']: qd = dictify_querystring(request.META['QUERY_STRING']) else: qd = None data = request.POST.copy() if len(selected) == 0 and data['action'] in ('export_to_csv', 'extended_export_to_csv'): ct = ContentType.objects.get_for_model(queryset.model) klass = ct.model_class() if qd: queryset = klass.objects.filter(**qd)[:65535] # cap at classic Excel maximum minus 1 row for headers else: queryset = klass.objects.all()[:65535] # cap at classic Excel maximum minus 1 row for headers return getattr(self, data['action'])(request, queryset) else: return super(ModelAdminCSV, self).response_action(request, queryset)

3
投票
它也在
django.contrib.admin.options.py

函数中也使用,因此您不能仅覆盖ChangElist_template并使用它 - 定义您自己的Action-vality Checker和Runner最容易。

如果您真的想使用该下拉列表,这是一个没有保证的想法。

如何定义无选admin操作的新属性:

action_failed = False selected = request.POST.getlist(helpers.ACTION_CHECKBOX_NAME) # Actions with no confirmation if (actions and request.method == 'POST' and 'index' in request.POST and '_save' not in request.POST): if selected: response = self.response_action(request, queryset=cl.get_query_set()) if response: return response else: action_failed = True else: msg = _("Items must be selected in order to perform " "actions on them. No items have been changed.") self.message_user(request, msg) action_failed = True

复制在您的被限制的某种程度上,仅在指定特定标志的动作上起作用,然后返回“真实”

response_action


myaction.selectionless = True

当调用“真实”动作时,您仍然会遇到错误。如果调用了覆盖措施,您可以可能修改请求。以删除该操作。 
其他方法涉及黑客太多的东西。我至少认为。


我对@AndyTheentity响应进行了更改,以避免每行一次调用操作。

response_action

I使用以下混音来创建不需要用户至少选择一个对象的操作。它还允许您获取用户刚刚过滤的QuerySet:

Https://gist.github.com/rafen/eff7adae38903eee766600CFF40B8B659

在此示例中如何使用它(还有更多有关如何在链接上使用它的信息):
changelist_view
    

由于对象选择不是您需要的一部分,听起来您可以通过创建自己的管理视图来最好地为您服务。

使自己的管理员视图非常简单:

写视图函数


3
投票
changelist_view

装饰器

添加了指向该视图的urlconf模式
通过误差相关的管理模板来添加指向它的链接

1
投票

ok,对于你们中的那些人足够顽固地想要这种工作,这是一个丑陋的黑客(对于Django 1.3),即使您没有选择任何东西,也可以采取任何行动。 您必须愚弄原始的changelist_view以为您选择了一些东西。

# There can be multiple action forms on the page (at the top # and bottom of the change list, for example). Get the action # whose button was pushed. try: action_index = int(request.POST.get('index', 0)) except ValueError: action_index = 0 # Construct the action form. data = request.POST.copy() data.pop(helpers.ACTION_CHECKBOX_NAME, None) data.pop("index", None) # Use the action whose button was pushed try: data.update({'action': data.getlist('action')[action_index]}) except IndexError: # If we didn't get an action from the chosen form that's invalid # POST data, so by deleting action it'll fail the validation check # below. So no need to do anything here pass action_form = self.action_form(data, auto_id=None) action_form.fields['action'].choices = self.get_action_choices(request) # If the form's valid we can handle the action. if action_form.is_valid(): action = action_form.cleaned_data['action'] select_across = action_form.cleaned_data['select_across'] func, name, description = self.get_actions(request)[action] if func.selectionless: func(self, request, {})

SO,在您的modelAdmin中,您覆盖changelist_view添加到请求中。
在您的操作中,您可以检查是否没有选定的项目:

0
投票
不用说您不应该这样做。

我发现的最简单解决方案是根据django

docs创建您的django admin函数,然后在您的网站admin中随机选择任何对象并运行该函数。这会将项目传递到您的功能,但您根本不会在任何地方使用它,因此它是多余的。为我工作。
  1. django管理员需要至少一个选定的对象才能执行操作。
    隐藏的复选框模拟具有ID =0
    的不存在的对象的选择
  2. admin.py
  3. @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
  4. Path_to_templates/custom_changelist.html
  5. @staff_member_required

© www.soinside.com 2019 - 2025. All rights reserved.