Henrik Poulsen
Henrik Poulsen

Reputation: 995

Pass variable to Python Flask form

I'm currently stuck trying to build a variable message flashing function for my Flask forms

Since I'm building a tool that has to have multiple languages available, I wish to create custom messages for my flask form validation based on specific language input.

My form looks something like this:

class messageForm(FlaskForm):
    title = StringField(
        'title',
        validators=[
            validators.DataRequired(validationMessage('validateRequired', language=language))
        ]
    )

the function "validationMessage" looks like this:

def validationMessage(message, language):
    msg = Message.query.filter_by(title=message).first()
    lang = Language.query.filter_by(abbr=language).first()
    text = messageBody.query.filter_by(message_id=msg.id, language_id=lang.id).first().text
    return text

As you notice, I do some lookup in a few database tables to produce my message text.

My trouble is now... How do I pass my language variable from my view to my form so that I can pass it on to the "validationMessage" function?

The language variable is based on a variable in my view endpoint

# Messages
@admin.route('/<string:language>/message', methods=['GET'])
def messageView(language='dk')
    form=messageForm()
    ...

I have considered using my session for this, but as I understand it, I can only use this within my view and therefore not within either my form or the message function

Upvotes: 2

Views: 6331

Answers (1)

MrLeeh
MrLeeh

Reputation: 5589

You can solve this problem by using the global context variable g. The trick is not to use the builtin validator but a custom validator. The reason is that the builtin validator is a factory function. This means the validationMessage function you pass to it will only be executed on class creation. If you build a custom validator and read the language from the global context variable it will work.

def custom_validator(form, field):
    language = g.language
    msg = Message.query.filter_by(title=message).first()
    lang = Language.query.filter_by(abbr=language).first()
    text = messageBody.query.filter_by(message_id=msg.id, language_id=lang.id).first().text

    if not len(field.data):
        raise validators.ValidationError(text)

Replace the validator in your form with the custom validator:

class messageForm(FlaskForm):
    title = StringField('title', validators=[custom_validator])

In the view function just create the language property for the global context variable.

# Messages
@admin.route('/<string:language>/message', methods=['GET'])
def messageView(language='dk')
    g.language = language
    form=messageForm()
    ...

Upvotes: 1

Related Questions