django内联操作将操作添加到modeladmin或inlinemodeladmin的每一行。

django-inline-actions的Python项目详细描述


django内联操作

pypiBuild StatusCoveragepython versionProject statuslicense

django内联操作将操作添加到inline modeladmin和modeladmin变更列表。

屏幕截图

Changelist exampleInline example

安装

注意如果您在django<2.0上,则必须使用django-inline-actions<2.0

  1. 安装django内联操作

    pip install django内联操作

  2. inline_actions添加到INSTALLED_APPS中。

集成

InlineActionsModelAdminMixin添加到ModelAdmin中。 如果要在内联线上执行操作,请将InlineActionMixin添加到InlineModelAdmin。 每个操作都作为ModelAdmin/InlineModelAdmin上的方法实现,并且必须具有以下签名。

def action_name(self, request, obj, parent_obj=None):
ArgumentDescription
^{}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'
ArgumentDescription
^{}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中的每一篇文章中添加两个简单的操作(viewunpublish)。 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

欢迎加入QQ群-->: 979659372 Python中文网_新手群

推荐PyPI第三方库


热门话题
java如何将cassandra中的行数据转换为与列相关的嵌套json   java如何使用jcr XPath在jcr:content/@jcr:data中搜索?   java在使用openCV进行安卓开发时如何利用手机的广角镜头   java解析扩展了接口,结束了一个潜在的无限循环   位置服务的@Override方法中存在java Android应用程序错误   java本地线程的用途和需求是什么   具有左右子访问的java节点树遍历   java验证JsonWebToken签名   JUL日志处理程序中的java日志记录   嵌入式Java读取给定时间段的串行数据。   java有没有办法从多个URL获取多个图像?   java线程通过等待intent阻止自己发送intent   java Spring MVC解析多部分内容请求   java JPA/Hibernate静态元模型属性未填充NullPointerException   java格式错误的字符(需要引号,得到I)~正在处理   java为什么PrintWriter对象抛出FileNotFoundException?   java Neo4j未正确保存标签   java IE不加载图像