是否可以在Django Admin Inline中动态设置'extra'选项?
例如,如果Student类将Address类设置为Inline。 如果没有与Student关联的地址内联,则extra = 1。 如果有任何地址内联与学生关联,则extra = 0。
答案 0 :(得分:3)
不确定它是否有效且我对内联和此额外属性不太熟悉,但您可以继承django.contrib.admin.InlineModelAdmin
并将InlineModelAdmin.extra
属性替换为python property:
from django.contrib import admin
from myproject.myapp.models import MyInlineModel
class DynamicExtraInlineModelAdmin(admin.InlineModelAdmin):
@property
def extra():
return 1 if some_logic else 0
admin.site.register(MyInlineModel, DynamicExtraInlineModelAdmin)
答案 1 :(得分:3)
你可以利用继承..
// based on some condition
kwargs['extra'] = something
.........
return super(*******Inline, self).get_formset(request, obj, **kwargs) // 'defaults.update(kwargs)' takes care of the dynamic overriding
我项目中的get_formset方法:
def get_formset(self, request, obj=None, **kwargs):
## Put in your condition here and assign extra accordingly
if obj is None:
return super(ImageInline, self).get_formset(request, obj, **kwargs)
current_topic = TopicPage.objects.get(pk = obj.id)
topic_images = ThruImage.objects.filter(topic = current_topic)
kwargs['extra'] = 0
if len(topic_images) <= 3:
kwargs['extra'] = 3 - len(topic_images)
return super(ImageInline, self).get_formset(request, obj, **kwargs)
这当然只对基于父模型对象的简单条件有用..
答案 2 :(得分:1)
你只需要修补django的(1.3.1)源代码如下:
首先将以下代码添加到您的应用中:
from django.forms.models import inlineformset_factory
from django.contrib.admin.util import flatten_fieldsets
from django.utils.functional import curry
from django.contrib.admin.options import InlineModelAdmin
class MyInlineModelAdmin(InlineModelAdmin):
#extra = 1
def get_formset(self, request, obj=None, **kwargs):
"""Returns a BaseInlineFormSet class for use in admin add/change views."""
if self.declared_fieldsets:
fields = flatten_fieldsets(self.declared_fieldsets)
else:
fields = None
if self.exclude is None:
exclude = []
else:
exclude = list(self.exclude)
exclude.extend(kwargs.get("exclude", []))
exclude.extend(self.get_readonly_fields(request, obj))
# if exclude is an empty list we use None, since that's the actual
# default
exclude = exclude or None
if obj and hasattr(obj, 'id'): # <<=======================================
_extra = 0
else:
_extra = self.extra
defaults = {
"form": self.form,
"formset": self.formset,
"fk_name": self.fk_name,
"fields": fields,
"exclude": exclude,
"formfield_callback": curry(self.formfield_for_dbfield, request=request),
"extra": _extra,
"max_num": self.max_num,
"can_delete": self.can_delete,
}
defaults.update(kwargs)
return inlineformset_factory(self.parent_model, self.model, **defaults)
class MyTabularInline(MyInlineModelAdmin):
template = 'admin/edit_inline/tabular.html'
并假设您的模型类似于:
class ContainerModel(models.Model):
pass #etc...
class ListModel(models.Model):
pass #etc...
然后将您的管理员更改为:
class ListModelInline(MyTabularInline): # <<=================================
model = MyModel
class ContainerModelAdmin(admin.ModelAdmin):
inlines = (ListModelInline,)
admin.site.register(ContainerModel, ContainerModelAdmin)
#etc...
答案 3 :(得分:1)
只需覆盖 get_extra 方法即可。以下示例将Extra视图的Extra设置为0,将Edit视图的Extra设置为10。
class MyInline(admin.TabularInline):
model = MyModel
def get_extra(self, request, obj=None, **kwargs):
return 0 if obj else 10