Django admin 不同的内联用于更改和添加视图
Posted
技术标签:
【中文标题】Django admin 不同的内联用于更改和添加视图【英文标题】:Django admin different inlines for change and add view 【发布时间】:2011-01-15 04:24:33 【问题描述】:我需要单独的视图来添加和更改页面。在添加页面中,我想从内联表单集中排除一些字段。我准备了两个 TabularInline 类,其中一个包含属性“排除”。我尝试按如下方式使用它们:
class BoxAdmin(admin.ModelAdmin):
def change_view(self, request, obj_id):
self.inlines=[ItemChangeInline,]
return super(BoxAdmin, self).change_view(self.request, obj_id)
def add_view(self, request):
self.inlines=[ItemAddInline,]
return super(BoxAdmin, self).add_view(self, request)
没有效果(根本没有显示内联)。
【问题讨论】:
【参考方案1】:它适用于 Django 1.5+ 并且看起来很优雅:
// admin.py
class BoxAdmin(ModelAdmin):
inlines = ()
def change_view(self, request, object_id, form_url='', extra_context=None):
self.inlines = (ItemChangeInline, )
return super(BoxAdmin, self).change_view(request, object_id)
def add_view(self, request, form_url='', extra_context=None):
self.inlines = (ItemAddInline, )
return super(BoxAdmin, self).add_view(request)
希望对大家有用
【讨论】:
我逐字使用它并且它有效,但我用return super(BoxAdmin, self).change_view(request, object_id, form_url, extra_context)
和return super(BoxAdmin, self).add_view(request, form_url, extra_context)
替换了两个返回【参考方案2】:
这是似乎可以工作的代码:
class BoxAdmin(admin.ModelAdmin):
def change_view(self, request, obj_id):
self.inlines=[ItemChangeInline,]
for inline_class in self.inlines:
inline_instance = inline_class(self.model, self.admin_site)
self.inline_instances.append(inline_instance)
return super(BoxAdmin, self).change_view(request, obj_id)
def add_view(self, request):
self.inlines=[ItemAddInline,]
for inline_class in self.inlines:
inline_instance = inline_class(self.model, self.admin_site)
self.inline_instances.append(inline_instance)
return super(BoxAdmin, self).add_view(request)
但是,这看起来不优雅,因为这部分:
for inline_class in self.inlines:
inline_instance = inline_class(self.model, self.admin_site)
self.inline_instances.append(inline_instance)
是 admin.ModelAdmin 的 init 方法的复制粘贴(因此它运行两次)。
【讨论】:
【参考方案3】:为什么在 add_view 中有 .add_view(self, request)
而在更改视图中有 .change_view(self.request, ..)
?我相信,您不需要在 add_view 中使用 self,因为您使用的是 super。
【讨论】:
【参考方案4】:我遇到了一种情况,我需要根据您为给定故事使用的管理站点显示内联。
扩展 alekwisnia 的答案,我能够使用以下代码获得适用于 Django 1.3 的动态内联:
在 highlight/admin.py 中
class HighlightInline(generic.GenericTabularInline):
model = Highlight
extra = 1
max_num = 4
fields = ('order', 'highlight')
template = 'admin/highlights/inline.html'
class HighlightAdmin(admin.ModelAdmin):
def regulate_highlight_inlines(self):
highlights_enabled = Setting.objects.get_or_default('highlights_enabled', default='')
highlight_inline_instance = HighlightInline(self.model, self.admin_site)
highlight_found = any(isinstance(x, HighlightInline) for x in self.inline_instances)
if highlights_enabled.strip().lower() == 'true':
if not highlight_found:
self.inline_instances.insert(0, highlight_inline_instance)
else:
if highlight_found:
self.inline_instances.pop(0)
print self.inline_instances
def change_view(self, request, object_id, form_url='', extra_context=None):
self.regulate_highlight_inlines()
return super(HighlightAdmin, self).change_view(request, object_id)
def add_view(self, request, form_url='', extra_context=None):
self.regulate_highlight_inlines()
return super(HighlightAdmin, self).add_view(request, form_url, extra_context)
在故事/admin.py中
class StoryAdmin(HighlightAdmin):
需要注意的一点是,我不仅仅是在操作内联类 (HighlightInline),而是在更改内联实例 (HighlightInline(self.model, self.admin_site))。这是因为 django 在 admin 类的初始构建过程中,已经根据内联类列表构建了内联实例列表。
【讨论】:
【参考方案5】:Django 1.3 的另一种解决方案
class BoxAdmin(admin.ModelAdmin):
def change_view(self, request, object_id, form_url='', extra_context=None):
self.inline_instances = [ItemChangeInline(self.model, self.admin_site)]
return super(BoxAdmin, self).change_view(request, object_id, extra_context)
def add_view(self, request, form_url='', extra_context=None):
self.inline_instances = [ItemAddInline(self.model, self.admin_site)]
return super(BoxAdmin, self).add_view(request, form_url, extra_context)
【讨论】:
【参考方案6】:受到你们回答的启发, 我能够向 admin.site 添加更多自定义视图。
很多时候,只是想要add
和change
不同设置的页面,而不是真正的额外浏览量
# admin.py
class FooAdmin(admin.ModelAdmin):
....
def edit_tag(self, obj): # add a Link tag to change-list page
return mark_safe('<a href="?edit=True">Edit</a>'.format(obj.get_absolute_url()))
edit_tag.short_description = u'Extra Action'
def change_view(self, request, object_id, form_url='', extra_context=None):
if request.GET.get('edit', False):
self.readonly_fields = (
'total_amount',
)
self.inlines = []
else:
self.readonly_fields = (
'name', 'client', 'constructor', 'total_amount'
)
self.inlines = [TransactionInline]
return super(ProjectAdmin, self).change_view(request, object_id)
def add_view(self, request, form_url='', extra_context=None):
self.readonly_fields = (
'total_amount',
)
self.inlines = []
return super(ProjectAdmin, self).add_view(request)
在此之后,我将拥有三个视图:
添加视图 - 无需内联表单集,无需添加相关对象。
更改视图 1 - 使用内联表单集,仅用于添加内联数据(相关对象),对象的字段是只读的。
更改视图 2 - 没有内联表单集,仅用于更改对象。
真的很简单,我们可以做得更多,谢谢大家。
【讨论】:
以上是关于Django admin 不同的内联用于更改和添加视图的主要内容,如果未能解决你的问题,请参考以下文章
Django Admin Cookbook-23如何在Django admin中添加嵌套的内联