我有一个模型,我希望工作人员能够编辑到事件的日期。喜欢这个:
class ThingAdmin(admin.ModelAdmin):
model = Thing
if obj.date < today: #Something like that
inlines = [MyInline,]
问题是,我无权访问此级别的obj实例。我已经尝试重写get_formset(),但没有得到任何结果。
请指教?
我有一个模型,我希望工作人员能够编辑到事件的日期。喜欢这个:
class ThingAdmin(admin.ModelAdmin):
model = Thing
if obj.date < today: #Something like that
inlines = [MyInline,]
问题是,我无权访问此级别的obj实例。我已经尝试重写get_formset(),但没有得到任何结果。
请指教?
感谢对1.4中的更改的评论。我在这里的实现也不是线程安全的,所以它确实应该被删除。
以来 get_formsets
传递对象并调用 get_inline_instances
,我们可以修改两个函数来对象进行操作。
这应该工作:
class ThingAdmin(admin.ModelAdmin):
model = Thing
inlines = [inline]
other_set_of_inlines = [other_inline]
def get_inline_instances(self, request, obj=None):
# ^^^ this is new
inline_instances = []
if obj.date > datetime.date(2012, 1, 1):
inlines = self.inlines
else:
inlines = self.other_set_of_inlines
for inline_class in inlines:
inline = inline_class(self.model, self.admin_site)
if request:
if not (inline.has_add_permission(request) or
inline.has_change_permission(request) or
inline.has_delete_permission(request)):
continue
if not inline.has_add_permission(request):
inline.max_num = 0
inline_instances.append(inline)
return inline_instances
def get_formsets(self, request, obj=None):
for inline in self.get_inline_instances(request, obj):
# ^^^^^ this is new
yield inline.get_formset(request, obj)
感谢对1.4中的更改的评论。我在这里的实现也不是线程安全的,所以它确实应该被删除。
以来 get_formsets
传递对象并调用 get_inline_instances
,我们可以修改两个函数来对象进行操作。
这应该工作:
class ThingAdmin(admin.ModelAdmin):
model = Thing
inlines = [inline]
other_set_of_inlines = [other_inline]
def get_inline_instances(self, request, obj=None):
# ^^^ this is new
inline_instances = []
if obj.date > datetime.date(2012, 1, 1):
inlines = self.inlines
else:
inlines = self.other_set_of_inlines
for inline_class in inlines:
inline = inline_class(self.model, self.admin_site)
if request:
if not (inline.has_add_permission(request) or
inline.has_change_permission(request) or
inline.has_delete_permission(request)):
continue
if not inline.has_add_permission(request):
inline.max_num = 0
inline_instances.append(inline)
return inline_instances
def get_formsets(self, request, obj=None):
for inline in self.get_inline_instances(request, obj):
# ^^^^^ this is new
yield inline.get_formset(request, obj)
我有一个复杂的案例,我尝试的解决方案以意想不到的方式失败(内联中只读字段的问题)。这是我发现的最明确和最安全的方式:
class MyAdmin(admin.ModelAdmin):
def add_view(self, request, form_url='', extra_context=None):
self.inlines = [InlineA, InlineC]
return super(MyAdmin, self).add_view(request, form_url, extra_context)
def change_view(self, request, object_id, form_url='', extra_context=None):
self.inlines = [InlineB, InlineC, InlineD]
return super(MyAdmin, self).change_view(request, object_id, form_url, extra_context)
这适用于Django 1.4.x.
在最新版本的Django中,您需要覆盖ModelAdmin.get_formsets。例如
class MyAdmin(admin.ModelAdmin):
def get_formsets(self, request, obj=None):
if obj:
for _ in super(MyAdmin, self).get_formsets(request, obj):
yield _
else:
for inline in self.get_specific_inlines(request):
yield inline.get_formset(request, obj)
我遇到的情况是,我需要根据您为特定故事提供的管理网站显示内联。
我能够使用以下代码获得为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)
在story / admin.py中
class StoryAdmin(HighlightAdmin):
需要注意的一点是,我不仅仅是在操作内联类(HighlightInline),而是在改变内联实例(HighlightInline(self.model,self.admin_site))。这是因为django已经在admin类的初始构造期间基于内联类列表构建了内联实例列表。
我认为最好的答案是在django文档中: https://docs.djangoproject.com/en/1.9/ref/contrib/admin/
搜索“get_inline_instances”提供的示例非常好,并详细描述了调用的细微差别。
我认为最简单的方法就是调用你的自定义功能 get_fields
, 要么 get_fieldsets
等等,只是设定 self.inlines
在自定义功能中。
class XXXAdmin(admin.ModelAdmin):
def set_inlines(self, request, obj):
""" hack inlines models according current request.user or obj """
self.inlines = []
if request.user.is_superuser or request.user is obj.recorder:
self.inlines = [AbcInline, ]
def get_fields(self, request, obj=None):
self.set_inlines(request, obj) # NOTICE this line
super(XXXAdmin, self).get_fields(request, obj)
现在最常见的方法是覆盖和超级调用get_inline_instances。
class ThingAdmin(models.ModelAdmin):
inlines = [MyInline,]
def get_inline_instances(self, request, obj=None):
unfiltered = super(ThingAdmin, self).get_inline_instances(request, obj)
#filter out the Inlines you don't want
keep_myinline = obj and obj.date < today
return [x for x in unfiltered if not isinstance(x,MyInline) or keep_myinline]
这可以在您需要时将MyInline放入,而不是在您不需要时。如果您知道您的班级中唯一的内联是MyInline,那么您可以使其更简单:
class ThingAdmin(models.ModelAdmin):
inlines = [MyInline,]
def get_inline_instances(self, request, obj=None):
if not obj or obj.date >= today:
return []
return super(ThingAdmin, self).get_inline_instances(request, obj)