我有一個模型,我希望工作人員能夠編輯事件的日期。像這樣:在Django admin中進行條件限制
class ThingAdmin(admin.ModelAdmin):
model = Thing
if obj.date < today: #Something like that
inlines = [MyInline,]
問題是,我沒有訪問此級別的obj實例。我試過覆蓋get_formset(),但沒有得到任何地方。
請指教?
我有一個模型,我希望工作人員能夠編輯事件的日期。像這樣:在Django admin中進行條件限制
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)
在最新版本的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)
我有一個複雜的案例,我嘗試的解決方案以意想不到的方式失敗(內聯只讀域的問題)。這是我找到的最清晰和最安全的方式:
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中的工作。
我遇到了一種情況,那就是我需要根據您對某個故事所在的管理站點顯示Inline。
我能得到動態的內嵌使用下面的代碼的Django 1.3工作:
在亮點/ 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已經基於內聯類的列表構建了內聯實例的列表。
我認爲最好的答案是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)
完美無瑕地工作。謝謝。 – 2011-03-24 15:40:44
從Django 1.4開始,這不起作用。 '__init__'似乎不再創建self.inline_instances,但現在有一個get_inline_instances()方法可以顯式覆蓋。 – Cerin 2013-02-12 22:08:32
似乎Cerin的評論現在已過時,因爲此答案已被修改爲使用get_inline_instances – 2014-06-23 13:17:34