django内联操作将操作添加到modeladmin或inlinemodeladmin的每一行。
django-inline-actions的Python项目详细描述
django内联操作
django内联操作将操作添加到inline modeladmin和modeladmin变更列表。
屏幕截图
安装
注意如果您在django<2.0
上,则必须使用django-inline-actions<2.0
。
安装django内联操作
pip install django内联操作
将
inline_actions
添加到INSTALLED_APPS
中。
集成
将InlineActionsModelAdminMixin
添加到ModelAdmin
中。
如果要在内联线上执行操作,请将InlineActionMixin
添加到InlineModelAdmin
。
每个操作都作为ModelAdmin
/InlineModelAdmin
上的方法实现,并且必须具有以下签名。
def action_name(self, request, obj, parent_obj=None):
Argument | Description |
---|---|
^{ | current request |
^{ | instance on which the action was triggered |
^{ | instance of the parent model, only set on inlines |
并且应该返回None
以返回到当前的变更表单或HttpResponse
。
最后,将方法名添加到在相应的ModelAdmin
上定义的操作列表inline_actions
。
如果要禁用actions列,则必须显式设置inline_actions = None
。
要动态添加操作,可以使用方法get_inline_actions(self, request, obj=None)
。
此模块捆绑了两个操作,用于查看(inline_actions.actions.ViewAction
)和删除(inline_actions.actions.DeleteAction
)。
只需将这些类添加到您的管理员中,就完成了。
此外,还可以添加方法来为每个对象生成自定义标签和css类。
如果有一个名为action_name
的内联操作,则可以定义
def get_action_name_label(self, obj):
return 'some string'
def get_action_name_css(self, obj):
return 'some string'
Argument | Description |
---|---|
^{ | instance on which the action was triggered |
每个定义的方法都必须返回一个字符串。
例1
想象一下一个简单的新闻应用程序,它具有以下admin.py
。
from django.contrib import admin
from inline_actions.admin import InlineActionsMixin
from inline_actions.admin import InlineActionsModelAdminMixin
from .models import Article, Author
class ArticleInline(InlineActionsMixin,
admin.TabularInline):
model = Article
inline_actions = []
def has_add_permission(self):
return False
@admin.register(Author)
class AuthorAdmin(InlineActionsModelAdminMixin,
admin.ModelAdmin):
inlines = [ArticleInline]
list_display = ('name',)
@admin.register(Article)
class AuthorAdmin(admin.ModelAdmin):
list_display = ('title', 'status', 'author')
我们现在要在AuthorAdmin
中的每一篇文章中添加两个简单的操作(view
,unpublish
)。
view
操作重定向到所选实例的changeform。
from django.core.urlresolvers import reverse
from django.shortcuts import redirect
class ArticleInline(InlineActionsMixin,
admin.TabularInline):
# ...
inline_actions = ['view']
# ...
def view(self, request, obj, parent_obj=None):
url = reverse(
'admin:{}_{}_change'.format(
obj._meta.app_label,
obj._meta.model_name,
),
args=(obj.pk,)
)
return redirect(url)
view.short_description = _("View")
由于unpublish
依赖于article.status
,我们必须使用get_inline_actions
动态添加此操作。
from django.contrib import admin, messages
from django.utils.translation import ugettext_lazy as _
class ArticleInline(InlineActionsMixin,
admin.TabularInline):
# ...
def get_inline_actions(self, request, obj=None):
actions = super(ArticleInline, self).get_inline_actions(request, obj)
if obj:
if obj.status == Article.PUBLISHED:
actions.append('unpublish')
return actions
def unpublish(self, request, obj, inline_obj):
inline_obj.status = Article.DRAFT
inline_obj.save()
messages.info(request, _("Article unpublished"))
unpublish.short_description = _("Unpublish")
将inline_actions
添加到变更列表的工作原理与此类似。有关详细信息,请参见示例项目(test_proj/blog/admin.py
)。
例2
与其为发布和取消发布创建单独的操作,不如选择在这两种状态之间切换的操作。
toggle_publish
实现上述行为。
def toggle_publish(self, request, obj, parent_obj=None):
if obj.status == Article.DRAFT:
obj.status = Article.PUBLISHED
else:
obj.status = Article.DRAFT
obj.save()
if obj.status == Article.DRAFT:
messages.info(request, _("Article unpublished."))
else:
messages.info(request, _("Article published."))
这可能会给用户留下一个模棱两可的按钮标签,因为无论内部状态如何,它都将被称为Toggle publish
。
我们可以通过添加特殊方法get_ACTIONNAME_label
来指定动态标签。
def get_toggle_publish_label(self, obj):
if obj.status == Article.DRAFT:
return 'Publish'
return 'Unpublish'
因此,假设一行中的对象具有DRAFT
状态,则按钮标签将为Toggle publish
,否则为Toggle unpublish
。
当我们创建一个方法,根据如下状态为每个对象添加css类时,我们会变得更加有趣:
def get_toggle_publish_css(self, obj):
if obj.status == Article.DRAFT:
return 'btn-red'
return 'btn-green'
你可以通过使用使你的按钮变绿的btn-green
和使你的按钮变红的btn-red
来让它更吸引眼球。
或者可以使用这些类添加一些javascript逻辑(即确认框)。
示例应用程序
使用捆绑测试应用程序可以看到django-inline-actions
正在运行。
使用^{
git clone https://github.com/escaped/django-inline-actions.git
cd django-inline-actions/
poetry install
poetry run pip install Django
cd test_proj
poetry run ./manage.py migrate
poetry run ./manage.py createsuperuser
poetry run ./manage.py runserver
在浏览器中打开^{
如何测试你的行为?
有两种方法可以为您的操作编写测试。 我们将在下面的示例中使用pytest。
测试动作本身
在对管理类本身调用操作之前,我们必须实例化管理环境并将其与模型的实例一起传递给ModelAdmin
。
因此,我们实现了一个名为admin_site
的fixture,它用于每个测试。
import pytest
from django.contrib.admin import AdminSite
from yourapp.module.admin import MyAdmin
@pytest.fixture
def admin_site():
return AdminSite()
@pytest.mark.django_db
def test_action_XXX(admin_site):
"""Test action XXX"""
fake_request = {} # you might need to use a RequestFactory here
obj = ... # create an instance
admin = MyAdmin(obj, admin_site)
admin.render_inline_actions(article)
response = admin.action_XXX(fake_request, obj)
# assert the state of the application
测试管理集成
或者,您可以在真正的django管理页面上测试您的操作。 您将必须登录,导航到相应的管理员并触发对操作的单击。 为了简化这个过程,可以使用django-webtest。 示例可以找到here。