简体   繁体   中英

Django MultiWidget and field labels

I have a requirement for a Django form that contains 3 forms.Textarea which are compressed into a single models.TextField compatible value. For this, I've subclassed both forms.MultiValueField and forms.MultiWidget . My problem is in trying to identify where and how to add labels to the widget's textarea inputs.

What I am currently doing is passing in the label value as an attr to the widget's subwidgets:

class ContentWidget(forms.MultiWidget):
    template_name = 'content_widget.html'

    def __init__(self, attrs=None):
        widgets = (
            forms.Textarea({'label': 'A'}),
            forms.Textarea({'label': 'B'}),
            forms.Textarea({'label': 'C'}),
        )
        super().__init__(widgets, attrs)

This lets me keep the content_widget.html pretty concise:

{% for subwidget in widget.subwidgets %}
  <label for="{{ subwidget.attrs.id }}">{{ subwidget.attrs.label }}</label>
  {% include subwidget.template_name with widget=subwidget %}
  <br />
{% endfor %}

But this also adds the label attr to each html element, which feels a bit hacky:

<textarea name="content_0" cols="40" rows="10" label="A" required="" id="id_content_0"></textarea>

Another option is to explicitly include it in a more long-form version of the template:

<label for="{{ widget.subwidgets.0.attrs.id }}">A</label>
{% include widget.subwidgets.0.template_name with widget=subwidget %}
...

However, for form elements in general, the label is assigned to the field , but I can't find a way for the widget to access them from the MultiValueField instance if I define them there:

class ContentField(forms.MultiValueField):
    def __init__(self, **kwargs):
        fields = (
            forms.CharField(label="A"),
            forms.CharField(label="B"),
            forms.CharField(label="C"),
        )
        super().__init__(fields, require_all_fields=False, **kwargs)

My concern is both that this makes the code harder to maintain and that this indicates I've missed something obvious here. My question is if there's a more consistent approach.

The only way I have found to do something similar is adding the placeholder attribute

class TimedeltaWidget(forms.MultiWidget):
    def __init__(self, fields, attrs=None, *args, **kwargs):
        fields[0].widget.attrs={'placeholder': _('Days')}
        fields[1].widget.attrs={'placeholder': _('Hours')}
        fields[2].widget.attrs={'placeholder': _('Minutes')}
        fields[3].widget.attrs={'placeholder': _('Seconds')}
        widgets = (fields[0].widget, fields[1].widget, fields[2].widget, fields[3].widget, )
        super(TimedeltaWidget, self).__init__(widgets, attrs)

Here the result:

结果图片

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM