代码之家  ›  专栏  ›  技术社区  ›  Emil Ivanov

创建使用两个<input>s的自定义django表单字段

  •  5
  • Emil Ivanov  · 技术社区  · 15 年前

    如何生成一个将自身呈现为一对输入的django字段 领域?

    理由:我正在尝试编写一个新的自定义字段。我会用它来 类似验证码的服务。这项服务的工作原理是提出一个问题- 然后收到一个和一个 令牌 . 验证通过发送 回答 以及 令牌 . 我想写一个表单域 封装此逻辑。元素应该呈现(imo)如下

    <input type="hidden" name="_token" value="1234567890" />
    <input type="text" name="answer" />
    

    一旦提交,我需要 _token answer 以验证答案。

    3 回复  |  直到 15 年前
        1
  •  2
  •   Felix Kling    15 年前

    看看 SelectDateWidget . 它将日期的输入拆分为三个选择框。

    医生说:

    这也可以作为具有多个html元素的小部件的示例,从而实现 value_from_datadict

        2
  •  9
  •   Wolph    15 年前

    我想你在找 MultiWidget ,只需给它2个常规小部件,它就会呈现组合。

        3
  •  4
  •   Dominik Szopa    15 年前

    这里有一个现成的例子(取自我的博客):

    class ComplexMultiWidget(forms.MultiWidget):
        def __init__(self, attrs=None):
            widgets = (
                forms.TextInput(),
                forms.SelectMultiple(choices=(('J', 'John'),
                                              ('P', 'Paul'),
                                              ('G', 'George'),
                                              ('R', 'Ringo'))),
                forms.SplitDateTimeWidget(),
            )
            super(ComplexMultiWidget, self).__init__(widgets, attrs)
    
        def decompress(self, value):
            if value:
                data = value.split(',')
                return [data[0], data[1],
                       datetime.datetime(*time.strptime(data[2],
                       "%Y-%m-%d %H:%M:%S")[0:6])]
            return [None, None, None]
        def format_output(self, rendered_widgets):
            return u'\n'.join(rendered_widgets)
    
    
    class ComplexField(forms.MultiValueField):
        def __init__(self, required=True, widget=None, label=None, initial=None):
            fields = (
                forms.CharField(),
                forms.MultipleChoiceField(choices=(('J', 'John'),
                                                   ('P', 'Paul'),
                                                   ('G', 'George'),
                                                   ('R', 'Ringo'))),
                forms.SplitDateTimeField()
            )
            super(ComplexField, self).__init__(fields, required,
                                               widget, label, initial)
    
        def compress(self, data_list):
            if data_list:
                return '%s,%s,%s' % (data_list[0],''.join(data_list[1]),
                                     data_list[2])
            return None
    

    示例如何使用:

    >>> f = ComplexField(widget=ComplexMultiWidget())
    >>> f.clean(['some text', ['J','P'], ['2007-04-25','6:24:00']])
    u'some text,JP,2007-04-25 06:24:00'
    >>> f.clean(['some text',['X'], ['2007-04-25','6:24:00']])
    Traceback (most recent call last):
    ...
    ValidationError: [u'Select a valid choice. X is not one of the available choices.']
    
    >>> f.clean(['some text',['JP']])
    Traceback (most recent call last):
    
    >>> class ComplexFieldForm(Form):
                field1 = ComplexField(widget=ComplexMultiWidget())
    
    >>> f = ComplexFieldForm({'field1_0':'some text','field1_1':['J','P'], 'field1_2_0':'2007-04-25', 'field1_2_1':'06:24:00'})
    >>> print f
    <tr><th><label for="id_field1_0">Field1:</label></th><td><input type="text" name="field1_0" value="some text" id="id_field1_0" />
    <select multiple="multiple" name="field1_1" id="id_field1_1">
    <option value="J" selected="selected">John</option>
    <option value="P" selected="selected">Paul</option>
    <option value="G">George</option>
    <option value="R">Ringo</option>
    </select>
    <input type="text" name="field1_2_0" value="2007-04-25" id="id_field1_2_0" /><input type="text" name="field1_2_1" value="06:24:00" id="id_field1_2_1" /></td></tr>
    
    >>> f.cleaned_data
    {'field1': u'some text,JP,2007-04-25 06:24:00'}