我正试图找出一种只有在Person.is_member为True时才显示以下RelativeInline的方法。
目前的admin.py:
class RelativeInline(admin.TabularInline):
model = Relative
fk_name = 'member'
class PersonAdmin(admin.ModelAdmin):
inlines = [RelativeInline,]
ordering = ('first_name',)
list_filter = ('is_member',)
search_fields = ('first_name', 'last_name',)
date_hierarchy = 'member_date'
list_display = ('first_name', 'last_name', 'is_member', 'member_date', 'photo')
admin.site.register(Person, PersonAdmin)
我能找到的唯一提示是我可以覆盖get_formset,但我找不到一个好的例子,所以我的微弱尝试不起作用。
这是我失败的尝试:
class RelativeInline(admin.TabularInline):
model = Relative
fk_name = 'member'
class PersonAdmin(admin.ModelAdmin):
ordering = ('first_name',)
list_filter = ('is_member',)
search_fields = ('first_name', 'last_name',)
date_hierarchy = 'member_date'
list_display = ('first_name', 'last_name', 'is_member', 'member_date', 'photo')
def get_formset(self, request, obj=None, **kwargs):
if obj.is_member:
inlines = [RelativeInline,]
return super(PersonAdmin, self).get_formset(request, obj, **kwargs)
admin.site.register(Person, PersonAdmin)
此代码不会生成任何错误,但无论Person.is_member是True还是False,都不会显示内联。
更新: 一位朋友建议我尝试改变:
inlines = [RelativeInline,]
为:
self.inlines = [RelativeInline,]
但无济于事。我也尝试过:
PersonAdmin.inlines = [RelativeInline,]
但结果是一样的 - 没有错误,没有内联。
答案 0 :(得分:3)
你原来的解决方案非常接近。如果查看第290行的django / contrib / admin / options.py,您将看到在实例化模型管理员时实例化内联类,之后忽略inlines
列表。因此,稍后在get_formsets()中设置此列表无效。
但是,你是正确的,get_formsets()是要覆盖的东西,以使你的内联成为条件。内联实例包含在self.inline_instances
中,因此要根据对象禁用它们(例如,我想隐藏“添加”表单上的特定内联),您可以覆盖它:
class MyAdmin(models.ModelAdmin):
inlines = [MyInline, SomeOtherInline]
def get_formsets(self, request, obj=None):
for inline in self.inline_instances:
if isinstance(inline, MyInline) and obj is None:
continue
yield inline.get_formset(request, obj)
答案 1 :(得分:1)
我决定改变整个范式并以不同的方式解决我的问题。我没有为具有条件内联的所有人设置单一管理员,而是决定:
最后,我认为这是一种更清洁的方法。现在可以维护成员,并且可以在内联中添加亲属(非成员)。 NonMemberAdmin允许编辑非成员。
<强> models.py:强>
class Person(models.Model):
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
is_member = models.BooleanField()
is_active = models.BooleanField(default=True)
class Meta:
verbose_name_plural = 'Members'
ordering = ('first_name', 'last_name')
class PersonProxy(Person):
class Meta:
proxy = True
verbose_name_plural = 'Non-Members'
class Relationship(models.Model):
name = models.CharField(max_length=50)
class Relative(models.Model):
member = models.ForeignKey(Person, related_name='relative_member')
relative = models.ForeignKey(Person, related_name='relative_relative')
relationship = models.ForeignKey(Relationship)
<强> admin.py:强>
class RelativeInline(admin.TabularInline):
model = Relative
fk_name = 'member'
class MemberAdmin(admin.ModelAdmin):
inlines = [RelativeInline,]
ordering = ('first_name',)
# list_filter = ('is_member',)
search_fields = ('first_name', 'last_name',)
# date_hierarchy = 'member_date'
list_display = ('first_name', 'last_name', 'member_date')
def queryset(self, request):
return (super(MemberAdmin, self).queryset(request)
.filter(is_member=True, is_active=True))
class NonMemberAdmin(admin.ModelAdmin):
ordering = ('first_name',)
search_fields = ('first_name', 'last_name',)
list_display = ('first_name', 'last_name')
def queryset(self, request):
return (super(NonMemberAdmin, self).queryset(request)
.filter(is_member=False, is_active=True))
admin.site.register(Person, MemberAdmin)
admin.site.register(PersonProxy, NonMemberAdmin)
答案 2 :(得分:0)
我意识到这个问题有点陈旧,而且代码库有所改变;现在有一个更清晰的要点覆盖事物:get_inline_instances
。你可以这样做:
class PersonAdmin(models.ModelAdmin):
inlines = [RelativeInline,]
def get_inline_instances(self, request, obj=None):
to_return = super(MyAdmin, self).get_inline_instances(request, obj)
#filter out the RelativeInlines if obj.is_member is false
if not obj or not obj.is_member:
to_return = [x for x in to_return if not isinstance(x,RelativeInline)]
return to_return