Django自定义Widget在选择1以上失败(输入整数)

时间:2016-07-22 19:17:09

标签: python html css django django-forms

我想要一个multiState点击框。所以我花了一些空闲的时间在一个很好的Django解决方案上:

DoctorObject model = (DoctorObject)getChild(groupPosition, childPosition);
String childText = model.getName();

这会创建一个类似于此处https://stackoverflow.com/a/33455783/3849359所说明的形式,然后点击切换下一个状态,直到它到达,然后在开头继续。

在我的视图中调用表单,如:

class MultiStateChoiceInput(forms.widgets.ChoiceInput):
    input_type = 'radio'
    def __init__(self, name, value, attrs, choice, index, label_id):
        # Override to use the label_id which is upped with 1
        if 'id' in attrs:
            self.label_id = attrs['id']+ "_%d" % label_id

        super(MultiStateChoiceInput, self).__init__(name, value, attrs, choice, index)

        self.value = force_text(self.value)


    @property
    def id_for_label(self):
        return self.label_id

    def render(self, name=None, value=None, attrs=None, choices=()):
        if self.id_for_label:           
            label_for = format_html(' for="{}"', self.id_for_label)
        else:
            label_for = ''
        attrs = dict(self.attrs, **attrs) if attrs else self.attrs
        return format_html(
            '{} <label{}>{}</label>',  self.tag(attrs), label_for, self.choice_label
        )


class MultiStateRenderer(forms.widgets.ChoiceFieldRenderer):
    choice_input_class = MultiStateChoiceInput

    outer_html = '<span class="cyclestate">{content}</span>'
    inner_html = '{choice_value}{sub_widgets}'

    def render(self):
        """
        Outputs a <ul> for this set of choice fields.
        If an id was given to the field, it is applied to the <ul> (each
        item in the list will get an id of `$id_$i`).

        # upgraded with the label_id
        """
        id_ = self.attrs.get('id')
        output = []
        for i, choice in enumerate(self.choices):
            choice_value, choice_label = choice
            if isinstance(choice_label, (tuple, list)):
                attrs_plus = self.attrs.copy()
                if id_:
                    attrs_plus['id'] += '_{}'.format(i)
                sub_ul_renderer = self.__class__(
                    name=self.name,
                    value=self.value,
                    attrs=attrs_plus,
                    choices=choice_label,
                    label_id = (i+1) % (len(self.choices))  # label_id is next one
                )
                sub_ul_renderer.choice_input_class = self.choice_input_class
                output.append(format_html(self.inner_html, choice_value=choice_value,
                                          sub_widgets=sub_ul_renderer.render()))
            else:
                w = self.choice_input_class(self.name, self.value,
                                            self.attrs.copy(), choice, i,  label_id = (i+1) % (len(self.choices)))  # label_id is next one
                output.append(format_html(self.inner_html,
                                          choice_value=force_text(w), sub_widgets=''))
        return format_html(self.outer_html,
                           id_attr=format_html(' id="{}"', id_) if id_ else '',
                           content=mark_safe('\n'.join(output)))


class MultiStateSelectWidget(forms.widgets.RendererMixin, forms.widgets.Select):
    ''' This widget enables multistate clickable toggles 
    Requires some css as well  (see .cyclestate)
    '''
    renderer = MultiStateRenderer

并且forms.py是:

SomeFormSet= modelformset_factory(myModel, form=myModelForm, extra=0)    
SomeFormSet.form = staticmethod(curry(myModelForm, somevariable=somevariable))

formset = SomeFormSet(request.POST or None, queryset=somequeryset)

我觉得它运作得很好。点击和保存工作正常(我有一个自定义保存方法)。除非表单字段的值为2或3,否则它会突然显示错误消息:&#39; field&#39;应该是一个整数。

如果有人能提供帮助那就太好了,因为我没有想法!

编辑:以防万一......我已经检查了POST,这很棒。唯一的问题是Django在解析POST的某个地方完全丢失了值(它变为None)如果值是2并且我不知道为什么。

EDIT2:似乎Django ModelForm也进行了模型验证。而模型是一个BooleanField,这就是它失败的原因。如果有人知道覆盖它的好方法,那就太好了!

1 个答案:

答案 0 :(得分:0)

@edgarzamora你的评论不是答案,但它很接近!

我从Form类Meta中删除了'field',所以它看起来像:

class Meta:
    model = MyModal
    fields = ('',)
    widgets = {'id': forms.HiddenInput(),
             }

现在一切正常,因为我有我的自定义保存方法......太愚蠢了,它花了我几个小时!谢谢!