After wandering around in the source, I think I've found the culprit code. In html.py -> Input class -> _post_processing function, there's the following condition:
elif t == 'radio': if str(self['value']) == str(self['_value']): self['_checked'] = 'checked' else: self['_checked'] = None When the radio button inputs are created by the form widgets, assuming no multiple values, both value and _value are set to the same option. Now I couldn't find when _post_processing is called, or if there's anywhere in the code that would change these two at some point, but it's pretty safe to say that variables are holding the same values after submission and thus both getting the checked attribute. When I removed this code everything worked as expected, and the radio list defaulted to the first value as I told it to. I believe the intention of this code is to have value be what the user selected or what is stored in the db, and then load all the inputs with this value, so that the conditions can display which value was selected though. This doesn't seem to be what's actually happening, and I don't even know if that part is implemented anywhere. If there's nothing else in the code to make this work, can it be removed? Or am I missing something that would make value and _value not be equal, and for some reason it's not working?