【问题标题】:ValueError when overriding the choices for a ForeignKey field in a model's admin覆盖模型管理中的 ForeignKey 字段的选项时出现 ValueError
【发布时间】:2013-02-06 13:00:58
【问题描述】:

我正在覆盖模型的管理表单以修改 ForeignKey 字段的 choices。 在管理表单中选择一个选项并保存时,我得到一个ValueError

Cannot assign "u'6'": "MyModel1.mymodel2" must be a "MyModel2" instance

其中6 是所选选项的ID。

新的choices 被构建为((<choice_1_id>, <choice_1_label>), (<choice_2_id>, <choice_2_label>),...),并且我为呈现的选择小部件获得了相同的html,就好像我没有修改choices 一样(当然除了排序)。

如果我在 MyModel1AdminForm.__init__() 中评论 self.fields['mymodel2'] = forms.ChoiceField(choices=choices),我不会收到任何错误...

有人可以帮忙吗?

models.py

class MyModel1(models.Model):
    mymodel2 = ForeignKey(MyModel2)
    # more fields...

admin.py

class MyModel1AdminForm(forms.ModelForm):

    class Meta:
        model = MyModel1

    def __init__(self, *args, **kwargs): 
        super(MyModel1AdminForm, self).__init__(*args, **kwargs)

        # create choices with ((<choice_1_id>, <choice_1_label>), (<choice_2_id>, <choice_2_label>),...)

        self.fields['mymodel2'] = forms.ChoiceField(choices=choices, widget=SelectWithDisabled) # http://djangosnippets.org/snippets/2453/


class MyModel1Admin(admin.ModelAdmin):
    form = MyModel1AdminForm
my_site.register(MyModel1, MyModel1Admin)

【问题讨论】:

    标签: django forms admin


    【解决方案1】:

    mymodel2 是外键字段。如果要更改选项而不是添加自定义选项,则需要提供查询集:

    self.fields['mymodel2'].queryset = MyModel2.objects.all()
    

    【讨论】:

    • 我实际上需要修改选项,因为我想禁用一些选项(我正在使用自定义选择小部件)。我更新了我的问题以将小部件添加到 forms.ChoiceField。
    【解决方案2】:

    如果您需要手动构建选择,例如

    choices = MyModel2.objects.values_list('pk', 'title')
    

    应该使用标准的ChoiceField,其中title 是您要用作标签/详细名称供您选择的模型字段。


    查看您正在使用的 sn-p values_list 将不起作用,因此您可以退回到列表理解:

    [(c.pk, {'label': c.title, 'disabled': False}) for c in MyModel2.objects.all()]
    

    虽然您显然需要更多逻辑来决定是启用还是禁用选项。

    【讨论】:

    • 保存时出现同样的 ValueError 错误。看来我应该使用forms.ModelChoiceField,但是我只能设置一个查询集,而不是选择。
    【解决方案3】:

    我最终覆盖了ModelChoiceField

    class MyModelChoiceField(forms.ModelChoiceField):
        def label_from_instance(self, obj):
            level = getattr(obj, obj._mptt_meta.level_attr)
            return {'label': obj.name), 'disabled': check_disabled(obj)}
    

    【讨论】:

      猜你喜欢
      • 2020-04-21
      • 2021-02-11
      • 1970-01-01
      • 2018-07-31
      • 1970-01-01
      • 2011-08-14
      • 2017-04-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多