2009-05-14 44 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