djangodjango-formsdjango-custom-field

Custom form field class with dynamic widget attributes


I often use Django form fields with various lengths. I would like to create a custom form field class MyFloatField with a dynamic widget attribute so I could set the max_width when defining each form field such as:

quantity = MyFloatField(label='Quantity:', max_width='50px')
price = MyFloatField(label='Price:', max_width='100px')

I have already created a custom form field where the max_width is a constant.

class MyFloatField(forms.FloatField):
    def widget_attrs(self, widget):
        attrs = super().widget_attrs(widget)
        attrs.setdefault("style", 'max-width: 50px')
        return attrs

I assume that in order to make it dynamic (pass the value from field definition) I need to somehow get the argument max_width='100px' from the definition of the form field and pass it as a variable to the attrs.setdefault(). I have tried the following but I get a TypeError: __init__() got an unexpected keyword argument 'max_width' error.

class MyFloatField(forms.FloatField):
    def widget_attrs(self, widget):
        my_max_width = kwargs['max_width']
        attrs = super().widget_attrs(widget)
        attrs.setdefault("style", 'max-width: '+my_max_width)
        return attrs

Any help would be greatly appreciated.


Solution

  • You were very close. If you want to use the value of your custom keyword argument max_length in the widget_attrs() function of an instance of the MyFloatField() class, you want to do the following.

    You want to assign the value of the max_length argument to the instance variable self.max_length within the class's __init__() method. By storing the value of max_length as an instance variable, it becomes accessible throughout the class, and thus, can be referenced in the widget_attrs() function. The class should thus look like this:

    class MyFloatField(forms.FloatField):
        def __init__(self, *, max_width='1000em', **kwargs):
            self.max_width_variable = max_width
            super().__init__(**kwargs)
    
        def widget_attrs(self, widget):
            my_max_width = self.max_width_variable
            attrs = super().widget_attrs(widget)
            attrs.setdefault("style", 'max-width: '+my_max_width)
            return attrs
    

    Note that both max_width_variable and my_max_width variables could both be called the same as the keyword (i.e. max_width). I have given them different names just so you are clear which variable is which.