可以为django管理员创建自定义的管理员操作,该操作不需要选择某些对象以运行它?
如果您尝试在不选择对象的情况下进行操作,则会收到消息:
Items must be selected in order to perform actions on them. No items have been changed.
有一种方法可以覆盖这种行为并让动作运行吗?
在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
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
有一种方法可以覆盖这个 行为并让动作运行 无论如何?
如果您抓取错误消息,则看到代码在
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)
如果您真的想使用该下拉列表,这是一个没有保证的想法。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
当调用“真实”动作时,您仍然会遇到错误。如果调用了覆盖措施,您可以可能修改请求。以删除该操作。其他方法涉及黑客太多的东西。我至少认为。
response_action
I使用以下混音来创建不需要用户至少选择一个对象的操作。它还允许您获取用户刚刚过滤的QuerySet:Https://gist.github.com/rafen/eff7adae38903eee766600CFF40B8B659
在此示例中如何使用它(还有更多有关如何在链接上使用它的信息):
changelist_view
由于对象选择不是您需要的一部分,听起来您可以通过创建自己的管理视图来最好地为您服务。使自己的管理员视图非常简单:
写视图函数
changelist_view
装饰器
添加了指向该视图的urlconf模式通过误差相关的管理模板来添加指向它的链接
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添加到请求中。
在您的操作中,您可以检查是否没有选定的项目:
我发现的最简单解决方案是根据django
docs创建您的django admin函数,然后在您的网站admin中随机选择任何对象并运行该函数。这会将项目传递到您的功能,但您根本不会在任何地方使用它,因此它是多余的。为我工作。隐藏的复选框模拟具有ID =0的不存在的对象的选择
@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
@staff_member_required