Django的ModelMultipleChoiceField对象没有to_field_name属性

10 投票
2 回答
18223 浏览
提问于 2025-04-17 06:37

我正在尝试为一个模型表单创建一个自定义字段。我是从 ModelMultipleChoiceField 这个类扩展的,然后重写了 render 和 render_options 方法,但每次我尝试导入我的表单时,都会遇到一个异常:

AttributeError: 'ModelMultipleChoiceField' object has no attribute 'to_field_name'

我不太明白我漏掉了什么。我甚至尝试在我的新类中添加一个 to_field_name 属性,但这也没有帮助。以下是我的代码:

class MultiSelect(ModelMultipleChoiceField):
def __init__(self, queryset, cache_choices=False, required=True,
             widget=None, label=None, initial=None, help_text=None, *args, **kwargs):
    super(MultiSelect, self).__init__(queryset, cache_choices, required, widget,
            label, initial, help_text, *args, **kwargs)

def render_options(self, name, choices, selected_choices):
    output = []
    i = 0
    for option_value, option_label in chain(self.choices, choices):
        checked_html = (option_value in selected_choices) and u' checked="checked"' or ''
        class_html = (i % 2 == 0) and u'even' or u'odd'
        output.append('<li class="{0}"><input type="checkbox" name="{1}" value="{2}"{3}/>{4}</li>'
                .format(class_html, name, escape(option_value), checked_html, escape(option_label)))
        i += 1

def render(self, name, value, attrs=None, choices=()):
    if value is None: value = []
    final_attrs = self.build_attrs(attrs, name=name)
    output = [u'<ul class="multiSelect">']
    options = self.render_options(name, choices, value)
    if options:
        output.append(options)
    output.append('</ul>')
    return mark_safe(u'\n'.join(output))


class RoleForm(ModelForm):
    class Meta:
        model = Role
        exclude = ('user_id',)
        widgets = {
            'permissions': MultiSelect(queryset=Permission.objects.all())
        }

每当我简单地执行 from myapp.forms import RoleForm 时,就会出现上面的错误。

我是不是应该在我的类中添加一些我遗漏的东西呢?

2 个回答

3

根据你提供的代码,我不太明白为什么会出现问题,不过 to_field_nameModelChoiceField 的一个属性。

class ModelChoiceField(ChoiceField):
    ...

    def __init__(self, queryset, empty_label=u"---------", cache_choices=False,
                 required=True, widget=None, label=None, initial=None,
                 help_text=None, to_field_name=None, *args, **kwargs):
        ...            

        self.to_field_name = to_field_name

但是,当 ModelMultipleChoiceField 继承自 ModelChoiceField 时,它的 __init__ 方法并不接受 to_field_name 作为一个关键字参数。看起来它是依赖于 ModelChoiceField 的默认行为,把 self.to_field_name 设置为默认值 None

你的子类应该也这样做,所以这一部分让人感到困惑。

23

看起来你对“字段”和“控件”搞混了。你是从 ModelMultipleChoiceField 这个类继承的,正如名字所示,它是一个字段,而不是控件。不过,renderrender_options 是控件的方法,而不是字段的方法。而且你在 widgets 字典里使用了你的类。

我猜你是想创建一个控件。你应该从一个控件类继承,可能是 forms.CheckboxSelectMultiple

撰写回答