1

全部,

我设法让 MultiValueField 和 MultiValueWidget 工作。但是,除了“选择”之外,我似乎无法向构成 MultiValueField 的子字段添加属性(如“标签”或“初始”)。

这是我的(简化的)代码:

class MyMultiWidget(django.forms.widgets.MultiWidget):
    def __init__(self,*args,**kwargs):
        myChoices = kwargs.pop("choices",[])
        widgets = (
            django.forms.fields.TextInput(),
            django.forms.fields.TextInput(),
            django.forms.fields.Select(choices=myChoices),
        )
        super(MyMultiWidget, self).__init__(widgets,*args,**kwargs)        

class MyMultiValueField(django.forms.fields.MultiValueField):
    widget = MyMultiWidget

    def __init__(self,*args,**kwargs):

        myLabel = "my label"
        myInitial = "my initial value"
        myChoices = [("a","a"),("b","b")]

        fields = (
            django.forms.fields.CharField(label=myLabel),
            django.forms.fields.CharField(initial=myInitial),
            django.forms.fields.ChoiceField(choices=myChoices),
        )
        super(MyMultiValueField,self).__init__(fields,*args,**kwargs)
        self.widget=MyMultiWidget(choices=myChoices)

class MyField(models.Field):

    def formfield(self,*args,**kwargs):
        return MyMultiValueField()

class MyModel(django.models.Model):
    myField = MyField(blank=True)

MyForm = modelform_factory(MyModel)

MyModel 的“myField”字段在 MyForm 中几乎可以正确呈现;它显示了三个小部件:两个 TextInput 和一个 Select。后者仅限于适当的选择。但前两者没有设置标签或初始值。

关于我做错了什么有什么建议吗?

谢谢。

4

4 回答 4

2

您应该定义format_output小部件的功能 - 请参阅:https ://docs.djangoproject.com/en/dev/ref/forms/widgets/

这允许您以任何您喜欢的方式格式化表单 html。我认为默认只是连接字段元素。

于 2012-08-30T14:54:41.257 回答
0

本提供的答案有点老套,我会使用'attrs'传递初始值:

forms.TextInput(attrs={'value': 'some text'})

有趣的是,某些属性似乎被正确传递了——例如在我的例子中,在 CharField 上设置 'max_length' 是有效的。

于 2014-02-14T21:37:44.870 回答
0

@george 是正确的,value可以静态定义,但您也可以覆盖get_context以在运行时计算值。

class MyInput(forms.CharField):
    def get_context(self, name, value, attrs):
        return super().get_context('some_name', 'some_value', attrs)

将渲染

<input type="text" name="some_name" value="some_value" ...>
于 2019-10-16T17:02:12.557 回答
0

我知道这个线程已经超过 9 年了,但我自己解决了这个问题(Python 3.9,Django 3.2)。

我最终做的是定义一个CharField要传递给MultiValueField构造函数的对象元组。CharField 对象使用我想要传递给的属性进行实例化MultiValueFieldwidget包括placeholder&value属性,以及help_text每个属性)。

placeholder是每个字段的一个非常有效的标签,value可以用作默认值。

value请注意,如果您在 a 上使用基于类的通用视图,则不能硬编码到字段中,ModelForm因为它会导致在打开UpdateView. 考虑到这一点,您必须为模型中的字段设置一个默认值(我使用了 a JSONField),然后在初始化后从表单实例中获取相关数据并将其传递给 multi_fields 元组中的字段构造函数。

编辑:不要忘记在表单的Meta类中包含模型字段。我发现如果你错过了这个,你的表单将不会保存新值。

然后,我将该元组作为fields参数传递给构造函数,并在元组上使用列表推导来动态定义widget(使用列表推导构建的自定义 MultiWidget)和help_text属性。

# MODELS.PY
from django import models


def default_multi_values():
    return {
        'Field1': 'Field1Value',
        'Field2': 'Field2Value'
    }


class ExampleModel(models.Model):
    example_field = models.JSONField(
        default=default_multi_values()
    )
# FORMS.PY
from django import forms


class CustomMultiWidget(forms.widgets.MultiWidget):
    
    def decompress(self, value):
        **do decompress**


class CustomMultiValueField(forms.MultiValueField):
    widget = CustomMultiWidget

    def compress(self, data_list):
        **do compress**


class CustomModelForm(forms.ModelForm):

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

        mf_values = self.instance.multi_value_field_here

        multi_fields = (
            forms.CharField(
                help_text='HelpText1',
                widget=forms.TextInput({
                    'placeholder': 'Placeholder1',
                    'value': mf_values['Field1']
                })
            ),
            forms.CharField(
                help_text='HelpText2',
                widget=forms.TextInput({
                    'placeholder': 'Placeholder2',
                    'value': mf_values['Field2']
                })
            ),
        )

        self.fields['multi_value_field_here'] = CustomMultiValueField(
            fields=multi_fields,
            widget=ColumnHeadersWidget(
                widgets=[field.widget for field in multi_fields],
            # Display an ordered list below the MultiWidget 
            # constructed from help_text messages from each consecutive field.
            help_text=
                f"<u><strong>MultiField Guide</strong></u></br>"
                f"{'</br>'.join(f'{multi_fields.index(field) + 1}: {field.help_text}' for field in multi_fields]}"
            )
        )

        class Meta:
            model = ExampleModel
            fields = [
                'example_field'
            ]
于 2021-12-06T10:49:46.617 回答