'Django 3.2 ModelForms with Legacy Database

I am using an old database designed a long time ago for a different backend. All the fields on the form that are checkboxes are saved to a CHAR(2) database fields - saving "ON" for true (or checked) or null for false.

I have been working with an older version of django (1.4) where I built a custom widget to enable the output of CheckboxInput to make sense to the DB.

Now the logic of widgets has changed its not working anymore, can anyone tell me what might be wrong with the following code, OR was my original approach too complex in the first place? (ie, should it be in the view?)

When I go to save, I get a error stating "form is not valid" with the message "Ensure this value has at most 2 characters (it has 4)" (if checked) or "...2 characters (it has 5)" (if unchecked).

So it seems that the Checkbox output is "True" or "False" even though the output of the html control is "on" or null!

class OnOffInput(Widget):
    def __init__(self, attrs=None, check_test=str):
        super(OnOffInput, self).__init__(attrs)
        # check_test is a callable that takes a value and returns True
        # if the checkbox should be checked for that value.
        self.check_test = check_test

    def render(self, name, value, attrs=None):
        final_attrs = self.build_attrs(attrs, type='checkbox', name=name)
        try:
            result = self.check_test(value)
        except: # Silently catch exceptions
            result = ''
        if result:
            final_attrs['checked'] = 'checked'
        if value not in ('', 'ON', False, None):
            # Only add the 'value' attribute if a value is non-empty.
            final_attrs['value'] = force_unicode(value)
        return mark_safe(u'<input%s />' % flatatt(final_attrs))

    def value_from_datadict(self, data, files, name):
        if name not in data:
            # A missing value means False because HTML form submission does not
            # send results for unselected checkboxes.
            return ''
        value = data.get(name.upper())
        # Translate true and false strings to boolean values.
        values =  {'true': 'ON', 'false': '', None: ''}
        if isinstance(value, basestring):
            value = values.get(value.upper(), value)
        return value

    def _has_changed(self, initial, data):
        # Sometimes data or initial could be None or u'' which should be the
        # same thing as False.
        return str(initial) != str(data)


Thanks in advance for any clues..



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source