简体   繁体   中英

How to use current_user in a flask-wtforms Validator

Is there a way to current_user in a custom field validator. It's almost as if the validator is instantiated at system set up time when there are no users rather then during the session call.

Thanks!

Have you tried doing something like the below? I don't know if it works but it allows you to define a static class at runtime and pass the current_user as an argument which the class inherits from global scope and doesnt mutate.

def form_generator(current_user):
    class web_form:
        user_email = StringFiled('Email', validators=[Email()])
        def validate_user_email(self, field)
            if Model.query.filter(field.data == current_user.email).first()
                return
            else:
                return ValidationError("Email is not current user's")
    return web_form()

In your flask route then try:

form = form_generator(current_user)

Sorry this is untested, i just saw it and posted a response. But if you try it let me know if it succeeds, or more interestingly why it failed!!

I haven't found a way to set validators at runtime, but there is a way to define a validation function for a field on a form class, and that function can be based on data passed to form at construction time. Here's an example

class MyForm(flask_wtf.FlaskForm):

    user_id_field = wtforms.StringField("User ID")

    def __init__(self, valid_user_id, **kwargs):

        super().__init__(**kwargs)
        self.valid_user_id = valid_user_id

    def validate_user_id_field(self, field):
        """
        Function name must be 'validate_' + name of field you want to validate
        """

        if field.data != self.valid_user_id

            raise wtforms.validators.ValidationError("Wrong user id!")


# In endpoint definition:
my_form = MyForm(formdata=flask.request.form, valid_user_id=flask_login.current_user.id)
my_form.validate()

Edit

Ha, turns out setting validators at runtime is incredibly easy, it's just that documentation doesn't mention it anywhere.

If you have a form with field some_field , you can simply set self.some_field.validators = [...] in form's constructor, eg

class MyForm(flask_wtf.FlaskForm):

    some_field = wtforms.HiddenField()

    def __init__(self, some_data, **kwargs):

        super().__init__(**kwargs)

        self.some_field.validators = [MyValidator(some_data)]

# In endpoint
form = MyForm(formdata=flask.request.form, some_data=some_data)

Or you can set validators directly in endpoint handler:

form = MyForm(formdata=flask.request.form)
form.some_field.validators = [MyValidator(some_data)]

While adding Validators at runtime is possible, it is not a good solution. The validator would have to be added after any initialization of the form!

In my opinion a better solution is to simply use a local import:

class ValidateIfUserMayDoThis:
    def __init__(self, message):
        self.message

    def __call__(self, form, field):
        from flask_login import current_user   # DO THE IMPORT HERE!!!!
        if current_user.username in ['Donald']:
            raise ValidationError(self.message)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM