FeinCMS 操作列的 Django 自定义管理操作

Django custom admin action for FeinCMS actions column

我正在使用 FeinCMS TreeEditor 界面为 Django-Mptt 树结构创建一个管理面板。此接口为每个节点提供了一个 'actions column' 用于快速添加或移动节点,而无需使用典型的 Django 管理操作 select 框。

我想做的是向该集合添加一个自定义管理操作,该操作将节点的 pk 传递给 celery 任务,然后该任务将添加一个节点集合作为子节点。现有函数只是指向该任务 (add/delete/move) 的 URL 的 href 链接,到目前为止,我只是简单地模仿了这个。

我的解决方案目前涉及:

  1. 将动作定义为模型上的函数
  2. 创建一个使用此函数并重定向回更改列表的视图
  3. 将此视图添加到管理 URLs
  4. 将 TreeEditor 操作列超级放入 ModelAdmin class
  5. 向调用此 URL
  6. 的集合添加一个操作

肯定有比这更好的方法吗?它有效,但感觉非常复杂和不干,我相信它会以奇怪的方式崩溃.

不幸的是,我才开始使用 Django 一两个月,所以我可能会使用一些明显的功能。我怀疑我可以用 get_urls() 做一些事情并直接在 ModelAdmin 中定义函数,或者在注入的 HTML 中使用代码块直接调用函数,尽管我不是确定它如何以及是否被认为是更好的选择。

代码: 我已将所有内容重命名为更简单的库 <> 书籍示例,以从上面的示例图像中删除不相关的功能。

models.py

class Library(models.Model):
    def get_books(self):
        # Celery task; file omitted for brevity
        get_books_in_library.delay(self.pk)

views.py

def get_books_in_library(request, library_id):
    this_library = Library.objects.get(pk=library_id)
    this_library.get_books_in_library()
    messages.add_message(request, messages.SUCCESS, 'Library "{0}" books requested.'.format(this_library.name))
    redirect_url = urlresolvers.reverse('admin:myapp_library_changelist')
    return HttpResponseRedirect(redirect_url)

urls.py

urlpatterns = [
    url(r'^admin/myapp/library/(?P<library_id>[0-9]+)/get_books/$', get_books_in_library, name='get books in library'),
    url(r'^admin/', include(admin.site.urls)),
]

admin.py

class LibraryAdmin(TreeEditor):
    model = Library
    def _actions_column(self, obj):
        actions = super(LibraryAdmin, self)._actions_column(obj)
        actions.insert(
            0, u'<a title="{0}" href="{1}/get_books"><img src="{2}admin/img/icon_addlink.gif" alt="{0}" /></a>'.format(
                _('Get Books'),
                obj.pk,
                settings.STATIC_URL
            )
        )
        return actions

请注意,如果您尝试执行此代码,我可能会在重命名和删除多余的内容时破坏某些内容,但我认为它应该充分说明我在这里尝试做的事情。

今天仔细研究并简单地尝试了各种其他解决方案后,我将一个使用 get_urls 的解决方案和一个直接定义到管理界面中的视图放在一起,虽然它实际上只是将代码从多个django 文件进入管理界面 - 虽然它确实使用管理包装器来阻止未经身份验证的用户,这是一个改进。

我会在这里留下一份工作代码的副本,供将来发现此代码的任何人使用,因为我很少看到 TreeEditor 等的示例。在较新版本的 Django 中使用。

class NodeAdmin(TreeEditor):
    model = Node
    # < ... > Other details removed for brevity
    def get_urls(self):
        urls = super(NodeAdmin, self).get_urls()
        my_urls = [
            url(r'^(?P<node_id>[0-9]+)/get_suggestions/$', self.admin_site.admin_view(self.get_suggestions)),
        ]
        return my_urls + urls

    def get_suggestions(self, request, node_id):
        this_node = Node.objects.get(pk=node_id)
        get_suggestions(this_node.pk)
        messages.add_message(request, messages.SUCCESS, 'Requested suggestions for {0}'.format(this_node.term))
        redirect_url = urlresolvers.reverse('admin:trinket_node_changelist')
        return HttpResponseRedirect(redirect_url)


    def _actions_column(self, obj):
        actions = super(NodeAdmin, self)._actions_column(obj)
        # Adds an 'get suggestions' action to the Node editor using a search icon
        actions.insert(
            0, u'<a title="{0}" href="{1}/get_suggestions"><img src="{2}admin/img/selector-search.gif" alt="{0}" /></a>'.format(
                _('Get Suggestions'),
                obj.pk,
                settings.STATIC_URL,
            )
        )
        # Adds an 'add child' action to the Node editor using a plus icon
        actions.insert(
            0, u'<a title="{0}" href="add/?{1}={2}"><img src="{3}admin/img/icon_addlink.gif" alt="{0}" /></a>'.format(
                _('Add child'),
                getattr(self.model._meta,'parent_attr', 'parent'),
                obj.pk,
                settings.STATIC_URL
            )
        )
        return actions