【问题标题】:how to modify choices on admin pages - django如何修改管理页面上的选择 - django
【发布时间】:2010-10-26 06:03:36
【问题描述】:

我有一个模型,它有一个名为“state”的字段:

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 更改为新状态时,其可能的选择集也会更改。

如何在管理员添加/更改页面上实现此功能?

【问题讨论】:

    标签: python django django-models django-admin


    【解决方案1】:

    我明白你想要做什么,但为什么不只显示所有这些,如果这个人选择(已经设置的)当前状态,就不要改变任何东西?

    您也可以使用表单构建视图来提供此功能

    【讨论】:

    • 这是一种可能,但不是一种非常优雅和安全的方法。更改状态会触发对要进行的数据的一些计算和修改,因此我真的不想信任用户,即使他们是管理员。
    【解决方案2】:

    您需要在该模型的 ModelAdmin 类中 use a custom ModelForm。在自定义 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
    

    【讨论】:

    • 管理员的“添加”视图会发生什么,因为没有 self.instance,你不能依赖实例进行过滤,如果有请求对象就好了跨度>
    • 是的,这个 ModelForm 需要处理 self.instance 的缺失并适当地设置初始可用选项。我不知道为什么请求对象是相关的,但您确实可以在 ModelAdmin.add_view (code.djangoproject.com/browser/django/trunk/django/contrib/…) 中访问它。
    • 是否可以更改模型本身的选择?毕竟,选项最初是在模型中指定的,在创建字段时。
    • 是的,你可以在重写的模型初始化方法中做类似的事情。刚刚问的问题是如何在管理员中做到这一点。
    • @CarlMeyer 嗨,我有一个与填充 admin.py 中的选项相关的问题,是否可以在课堂内设置类似:form = form1 list_editable = ('status') fields = ( 'field1', 'field2')。最初需要更改的 field2 选择在哪里?我已经创建了这个问题question_link,现在经过研究来到这个问题:) 谢谢
    【解决方案3】:

    这似乎是一些 javascript 的工作。您希望选择框中的项目列表根据其他内容(可能是复选框或单选按钮)的值进行更改。动态实现这一点的唯一方法——无需让用户保存表单并重新加载页面——是使用 javascript。

    您可以使用 ModelAdmin 的 Media 类在模型的管理页面中加载自定义 JavaScript,记录在 here

    【讨论】:

    • 不,他正在尝试根据同一字段的当前值设置字段的下一个值的选择 - 这是一个关键区别。因此,在客户端动态更改选项是不相关的;事实上,这会很混乱。
    【解决方案4】:

    当您为模型(例如 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 关系的选择。

    【讨论】:

      猜你喜欢
      • 2018-11-21
      • 2012-02-09
      • 2010-10-01
      • 2021-09-25
      • 2011-08-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-12-17
      相关资源
      最近更新 更多