Есть ли способ заставить пользовательские действия администратора Django появляться в представлении "изменение" в дополнение к представлению "список изменений"?
Я подумал, по какой причине это было бы легко сделать, но я выглядел глубже, и кажется, что нет простого способа разрешить пользователям выполнять пользовательские действия администратора в представлении "изменить" экземпляра (т.е. когда вы просто просмотр экрана редактирования для одного экземпляра, а не списка экземпляров).
Я пропустил простой способ сделать это? Или мой единственный выбор - переопределить один из шаблонов администратора (и, вероятно, метод ModelAdmin.add_view
)?
Ответы
Ответ 1
Вот обновление и улучшение этого ответа. Он работает с django 1.6 и перенаправляется туда, откуда вы пришли.
class ActionInChangeFormMixin(object):
def response_action(self, request, queryset):
"""
Prefer http referer for redirect
"""
response = super(ActionInChangeFormMixin, self).response_action(request,
queryset)
if isinstance(response, HttpResponseRedirect):
response['Location'] = request.META.get('HTTP_REFERER', response.url)
return response
def change_view(self, request, object_id, extra_context=None):
actions = self.get_actions(request)
if actions:
action_form = self.action_form(auto_id=None)
action_form.fields['action'].choices = self.get_action_choices(request)
else:
action_form = None
extra_context=extra_context or {}
extra_context['action_form'] = action_form
return super(ActionInChangeFormMixin, self).change_view(request, object_id, extra_context=extra_context)
class MyModelAdmin(ActionInChangeFormMixin, ModelAdmin):
......
Шаблон:
{% extends "admin/change_form.html" %}
{% load i18n admin_static admin_list admin_urls %}
{% block extrastyle %}
{{ block.super }}
<link rel="stylesheet" type="text/css" href="{% static "admin/css/changelists.css" %}" />
{% endblock %}
{% block object-tools %}
{{ block.super }}
<div id="changelist">
<form action="{% url opts|admin_urlname:'changelist' %}" method="POST">{% csrf_token %}
{% admin_actions %}
<input type="hidden" name="_selected_action" value="{{ object_id }}">
</form>
</div>
{% endblock %}
Ответ 2
Вот что я сделал.
Во-первых, я расширил change_view объекта ModelAdmin следующим образом:
def change_view(self, request, object_id, extra_context=None):
actions = self.get_actions(request)
if actions:
action_form = self.action_form(auto_id=None)
action_form.fields['action'].choices = self.get_action_choices(request)
else:
action_form = None
changelist_url = urlresolvers.reverse('admin:checkout_order_changelist')
return super(OrderAdmin, self).change_view(request, object_id, extra_context={
'action_form': action_form,
'changelist_url': changelist_url
})
В основном мы просто собираем данные, необходимые для заполнения раскрывающегося списка действий в представлении изменений.
Затем я просто расширил change_form.html для рассматриваемой модели:
{% extends "admin/change_form.html" %}
{% load i18n adminmedia admin_list %}
{% block extrastyle %}
{{ block.super }}
<link rel="stylesheet" type="text/css" href="{% admin_media_prefix %}css/changelists.css" />
{% endblock %}
{% block object-tools %}
{{ block.super }}
<div id="changelist">
<form action="{{ changelist_url }}" method="POST">{% csrf_token %}
{% admin_actions %}
<input type="hidden" name="_selected_action" value="{{ object_id }}">
</form>
</div>
{% endblock %}
Это почти идентично тому, как раздел действий администратора выводится в виде списка изменений. Основные отличия: 1) мне нужно было указать URL-адрес для формы для публикации, 2) вместо флажка, чтобы указать, какой объект следует изменить, значение устанавливается через скрытое поле формы и 3) Я включил CSS для просмотра списка изменений и запустил действия в div с идентификатором #changelist
- так, чтобы поле выглядело наполовину приличным.
Не отличное решение, но оно работает нормально и не требует дополнительной настройки для дополнительных действий, которые вы могли бы добавить.
Ответ 3
Что я сделал, так это создать мой собственный шаблон MYAPP/templates/admin/MYMODEL/change_form.html:
{% extends "admin/change_form.html" %}
{% load i18n %}
{% block object-tools %}
{% if change %}{% if not is_popup %}
<ul class="object-tools">
<li><a href="{% url MY_COMMAND_VIEW original.id %}" class="historylink" >MY COMMAND</a></li>
<li><a href="history/" class="historylink">{% trans "History" %}</a></li>
{% if has_absolute_url %}<li><a href="../../../r/{{ content_type_id }}/{{ object_id }}/" class="viewsitelink">{% trans "View on site" %}</a></li>{% endif%}
</ul>
{% endif %}{% endif %}
{% endblock %}
Поэтому я в основном только изменил блок "объектные инструменты", где связаны ссылки на историю и "вид на сайте". остальная часть оригинала change_form.html остается нетронутой.
BTW: "original.id" - это идентификатор модели, которую вы редактируете.