Search code examples
pythonflaskpython-babelflask-babel

Flask Babel convert to original language when insert to database


I have a set of SelectField with Flask-WTF and I convert the default language with Flask-Babel.

Here is the snippet of my code:

from flask_babel import _, lazy_gettext as _l

class PaymentStatus(enum.Enum):
    PENDING = _l('PENDING')
    COMPLETED = _l('COMPLETED')
    EXPIRED = _l('EXPIRED')

    def __str__(self):
        return '{}'.format(self.value)

payment_status = [(str(_l(y)), y) for y in (PaymentStatus)]

class PaymentForm(FlaskForm):
    status_of_payment = SelectField(_l('Payment Status'), choices=payment_status)
    # ...
    # ...

And here is my model look like:

class Payment(db.Model):
    __tablename__ = 'payment'
    id = db.Column(db.Integer, primary_key=True)
    status_of_payment = db.Column(db.Enum(PaymentStatus, name='status_of_payment'))
    # ...
    # ...

And when I try to insert the value from the Flask-WTF form to my database, I got some error.

Here is the snippet how I insert it to database:

if form.validate_on_submit():
    payment = Payment(
        # payment_status=form.status_of_payment.data
        payment_status=PaymentStatus.PENDING.value
        # ...
        # ...
    )

The value of the enum PENDING also converted to the language on preferred language on my browser, so I got this error message:

sqlalchemy.exc.StatementError: (builtins.LookupError) "MENGUNGGU" is not among the defined enum values

for more information: "MENGUNGGU" = is Indonesian language for "PENDING" in English.

So the problem here is, when I insert the SelectField value, it also converts the language to my preferred browser language, and my database which is PostgreSQL block it, because I don't define the value on my enum type.

So, the point of my question is, can we excluded the i18n & l10n value from Flask-Babel when we want to insert the value to a database..?, or what should I do to face this..?


Solution

  • You should swap values in your choices because the first element in the tuple is the actual value that will be submitted and the second one is the presentation:

    payment_status = [(y.name, _l(str(y.value))) for y in PaymentStatus]

    Thanks to this you'll have translated names and proper values submitted.

    Enum's name should be stored in your database instead of the value.