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 链接,到目前为止,我只是简单地模仿了这个。
我的解决方案目前涉及:
- 将动作定义为模型上的函数
- 创建一个使用此函数并重定向回更改列表的视图
- 将此视图添加到管理 URLs
- 将 TreeEditor 操作列超级放入 ModelAdmin class
- 向调用此 URL
的集合添加一个操作
肯定有比这更好的方法吗?它有效,但感觉非常复杂和不干,我相信它会以奇怪的方式崩溃.
不幸的是,我才开始使用 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
我正在使用 FeinCMS TreeEditor 界面为 Django-Mptt 树结构创建一个管理面板。此接口为每个节点提供了一个 'actions column' 用于快速添加或移动节点,而无需使用典型的 Django 管理操作 select 框。
我想做的是向该集合添加一个自定义管理操作,该操作将节点的 pk 传递给 celery 任务,然后该任务将添加一个节点集合作为子节点。现有函数只是指向该任务 (add/delete/move) 的 URL 的 href 链接,到目前为止,我只是简单地模仿了这个。
我的解决方案目前涉及:
- 将动作定义为模型上的函数
- 创建一个使用此函数并重定向回更改列表的视图
- 将此视图添加到管理 URLs
- 将 TreeEditor 操作列超级放入 ModelAdmin class
- 向调用此 URL 的集合添加一个操作
肯定有比这更好的方法吗?它有效,但感觉非常复杂和不干,我相信它会以奇怪的方式崩溃.
不幸的是,我才开始使用 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