2009-05-14 43 views
9

我有一個名爲「狀態」領域的典範:如何修改管理頁面選擇 - Django的

class Foo(models.Model): 
    ... 
    state = models.IntegerField(choices = STATES) 
    ... 

對於每一個狀態,可能的選擇是所有國家的某個子集。例如:

if foo.state == STATES.OPEN:  #if foo is open, possible states are CLOSED, CANCELED 
    ... 
if foo.state == STATES.PENDING: #if foo is pending, possible states are OPEN,CANCELED 
    ... 

因此,當foo.state更改爲新狀態時,其可能的選擇集也發生變化。

如何在Admin添加/更改頁面上實現此功能?

回答

9

您需要use a custom ModelForm在該模型中的ModelAdmin類。在自定義的ModelForm的__init__方法,可以動態設置該字段的選擇:

class FooForm(forms.ModelForm): 
    class Meta: 
     model = Foo 

    def __init__(self, *args, **kwargs): 
     super(FooForm, self).__init__(*args, **kwargs) 
     current_state = self.instance.state 
     ...construct available_choices based on current state... 
     self.fields['state'].choices = available_choices 

你會使用這樣的:

class FooAdmin(admin.ModelAdmin): 
    form = FooForm 
+0

管理員的「添加」視圖會發生什麼情況,因爲沒有self.instance,您不能依賴實例進行過濾,所以請求對象存在就很好 – 2009-07-28 02:03:07

+0

是的,此ModelForm需要處理缺少self.instance並適當設置最初的可用選項。我不知道爲什麼請求對象是相關的,但是您可以在ModelAdmin.add_view中訪問它(http://code.djangoproject.com/browser/django/trunk/django/contrib/admin/options.py# L704)。 – 2009-07-28 14:08:55

+0

是否有可能改變模型本身的選擇?畢竟,在創建字段時,最初在模型中指定了選項。 – 2012-06-06 12:47:02

-1

我看到你想要做什麼,但爲什麼不顯示所有的人,如果該人挑選(已設置)的當前狀態,只是不改變什麼?

,你也可以只建立與形式的視圖提供此功能

+0

這是一種可能性,但不是一個非常優雅和安全的。改變狀態會觸發對數據進行一些計算和修改,因此我真的不想信任用戶,即使他們是管理員。 – shanyu 2009-05-14 20:08:07

0

這似乎是一些JavaScript的工作。您希望選擇框中的項目列表根據其他值的大小進行更改,這可能是複選框或單選按鈕。動態發生這種情況的唯一方法就是使用javascript,而不必讓用戶保存表單並重新加載頁面。

您可以使用的ModelAdmin傳媒類加載模型的管理頁面自定義JavaScript,記錄here

+1

不,他試圖根據同一個字段的當前值設置字段下一個值的選項 - 一個關鍵的區別。所以動態改變客戶端的選項是不相關的;實際上它會很混亂。 – 2009-05-14 22:32:40

12

當您爲模型(例如MyModelAdmin)創建新的管理界面時,有特定的方法可以覆蓋字段的默認選項。對於通用choice field

class MyModelAdmin(admin.ModelAdmin): 
    def formfield_for_choice_field(self, db_field, request, **kwargs): 
     if db_field.name == "status": 
      kwargs['choices'] = (
       ('accepted', 'Accepted'), 
       ('denied', 'Denied'), 
      ) 
      if request.user.is_superuser: 
       kwargs['choices'] += (('ready', 'Ready for deployment'),) 
     return super(MyModelAdmin, self).formfield_for_choice_field(db_field, request, **kwargs) 

但你也可以選擇覆蓋爲ForeignKeyMany to Many關係。

+3

這應該是公認的答案,因爲它是最簡單和最好的解決方案。 – 2014-10-31 18:42:38

+0

@shanyu這應該是公認的答案,因爲它是解決問題的最佳方法。 – Jay 2018-01-03 05:40:57