Django - Admin - Inline - 基于某些条件的'额外'值

时间:2011-01-01 18:53:44

标签: django django-admin

是否可以在Django Admin Inline中动态设置'extra'选项?

例如,如果Student类将Address类设置为Inline。 如果没有与Student关联的地址内联,则extra = 1。 如果有任何地址内联与学生关联,则extra = 0。

4 个答案:

答案 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