How to set css class of a label in a django form declaration?

I found this snippet which may be a good answer:

How to add css class and "*" to required fields's labels

here an adaptation to my needs (not tested yet, I'll edit the post once done):

from django.utils.html import escape

def readonly_cssclass_adder(bound_field, label_content, label_attrs):
    if 'readonly' in bound_field.field.widget.attrs:
        if 'class' in attrs:
            label_attrs['class'] += " readOnly"
        else:
            label_attrs['class'] = "readOnly"
    return label_content, label_attrs
        

def add_required_label_tag(original_function, tweak_foos=None):
    if not tweak_foos:
        return original_function

    def required_label_tag(self, contents=None, attrs=None):
        contents = contents or escape(self.label)
        if attrs is None:
            attrs = {}
        for foo in tweak_foos:
            contents, attrs = foo(self, contents, attrs)
        return original_function(self, contents, attrs)
    return required_label_tag

def decorate_bound_field():
    from django.forms.forms import BoundField
    BoundField.label_tag = add_required_label_tag(BoundField.label_tag, 
                                           tweak_foos=[readonly_cssclass_adder])

If you have a better solution which don't tweak all the BoundField class I'm still listening.

edit: may be linked to django uniform way to handle required field but it seems to don't call readonly_cssclass_adder. But I found an other and easyer solution, my readOnly widget automatically turned readOnly ctrlHolder

This addition is my favorite response for now:

edit 2: The other way I choose at end was to "override" the uni_form/field.html template which don't call BoundField.label_tag. So I checked here field state.

<label for="{{ field.auto_id }}"{% if field.field.required %}
       class="requiredField{% if field.widget.attrs.readonly %} readOnlyLabel{% endif %}"
       {% else %}{% if field.widget.attrs.readonly %}class="readOnlyLabel"{% endif %}{% endif %}>
    {{ field.label|safe }}{% if field.field.required %}<span class="asteriskField">*</span>{% endif %}
</label>

Widgets have an attrs keyword argument that take a dict which can define attributes for the input element that it renders. Forms also have some attributes you can define to change how Django displays your form. Take the following example:

class MyForm(forms.Form):
    error_css_class = 'error'
    required_css_class = 'required'
    my_field = forms.CharField(max_length=10,
                               widget=forms.TextInput(attrs={'id': 'my_field',
                                                             'class': 'my_class'}))

This works on any Widget class. Unfortunately, there isn't an easy way to change how Django renders labels if you just do {{ field }}. Luckily, you play with the form object a little bit in the template:

<form>
    {% for field in form %}
        <label class="my_class" for="{{ field.auto_id }}">{{ field.label }}</label>
        {{ field }}
    {% endfor %}
    <button type="submit">Submit</button>
</form>

Then again, you can always add arbitrary attributes to the objects you're working with:

# In a view...
form = MyForm()
form.label_classes = ('class_a', 'class_b', )
# Or by hijacking ```__init__```
class MyForm(forms.Form):
    def __init__(self, *args, **kwargs):
        self.my_field = forms.CharField(max_length=10,
                                        widget=forms.TextInput(attrs={'id': 'my_field',
                                                                      'class': 'my_class'}))
        self.my_field.label_classes = ('class_a', 'class_b', )
        super(MyForm, self).__init__(*args, **kwargs)

Render your template with the form in context, and in the template you can do:

<form>
    {% for field in form %}
        <label class="{% for class in field.label_classes %}{{ class }} {% endfor %}"
               for="{{ field.auto_id }}">{{ field.label }}</label>
        {{ field }}
    {% endfor %}
    <button type="submit">Submit</button>
</form>

Whatever suits your fancy.