Erik Oosterwaal
Erik Oosterwaal

Reputation: 4374

Flask-WTF default for a SelectField doesn't work for SQLAlchemy enum types

I have a Flask-SQLAlchemy site which uses the SQLAlchemy enum type for certain columns, to restrict possible input values.

For example, I have a "payment type" enum that has a few payment type options, like so:

class PaymentType(enum.Enum):
    fixed = "fixed"
    variable = "fixed_delivery"
    quantity_discount = "quantity_discount"

When I use this in a dropdown/select I can specify the options like so:

prd_payment_type = SelectField(_('prd_payment_type'), choices=SelectOptions.PaymentTypes.All(0, _('PleaseSelect')))

The All() function I'm calling returns the different enum values as options, and also adds a custom "Please select..." option to the dropdown list. It looks like this:

class PaymentTypes(object):

    @staticmethod
    def All(blank_value=None, blank_text=None):
        ret = [(i.value, _(i.name)) for i in PaymentType]
        SelectOption.add_blank_item(ret, blank_value, blank_text)
        return ret

So far, so good, I get a nice dropdown, with the correct options. the problem arises when I want to display the form using an already existing SQLAlchemy object from the database.

When I fetch the object from SQLAlchemy, the prd_payment_type property contains the enum PaymentType.quantity_discount, not just a string value 'quantity_discount': enter image description here

Because WTForms (presumably) matches the pre-selected option in the dropdown to a string value "quantity_discount", it doesn't match the enum in the SQLAlchemy model and the option is not selected in the dropdown.

The SelectField of WTForms accepts a list of tuples containing strings as choices. I can't feed it my enum. On the other hand, the SQLAlchemy model returns an enum type as the property for prd_payment_type. I could maybe override this property or something, but that feels like a lot of work to support SQLAlchemy's enums in WTForms.

Is there a standard solution for working with SQLAlchemy's enums in a WTForms SelectField or should I abandon using enums altogether and just store strings, maybe from a list of constants to keep them in check?

Upvotes: 1

Views: 1119

Answers (1)

Erik Oosterwaal
Erik Oosterwaal

Reputation: 4374

I have found a solution myself. It seems that when the enum has a

def __str__(self):
    return str(self.value)

That's enough for WTForms to match the database value to the SelectField value. I have made a baseclass that derives from enum.Enum and added the code above to return the enum value as a string representation.

This solution was based on these similar problems I found later on:

https://github.com/flask-admin/flask-admin/issues/1315

Python Flask WTForm SelectField with Enum values 'Not a valid choice' upon validation

Upvotes: 1

Related Questions