2011-03-23 205 views
10

我有一個模型,我希望工作人員能夠編輯事件的日期。像這樣:在Django admin中進行條件限制

class ThingAdmin(admin.ModelAdmin): 
    model = Thing 

    if obj.date < today: #Something like that 
     inlines = [MyInline,] 

問題是,我沒有訪問此級別的obj實例。我試過覆蓋get_formset(),但沒有得到任何地方。

請指教?

回答

9

感謝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

完美無瑕地工作。謝謝。 – 2011-03-24 15:40:44

+0

從Django 1.4開始,這不起作用。 '__init__'似乎不再創建self.inline_instances,但現在有一個get_inline_instances()方法可以顯式覆蓋。 – Cerin 2013-02-12 22:08:32

+0

似乎Cerin的評論現在已過時,因爲此答案已被修改爲使用get_inline_instances – 2014-06-23 13:17:34

2

在最新版本的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) 
2

我有一個複雜的案例,我嘗試的解決方案以意想不到的方式失敗(內聯只讀域的問題)。這是我找到的最清晰和最安全的方式:

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中的工作。

0

我遇到了一種情況,那就是我需要根據您對某個故事所在的管理站點顯示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已經基於內聯類的列表構建了內聯實例的列表。

0

我認爲最簡單的方法來調用你的自定義功能get_fieldsget_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) 
0

現在最好的方法就是覆蓋和超級調用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)