wtforms raise a validation error after the form is validated
Asked Answered
A

2

11

I have a registration form that collects credit card info. The workflow is as follows:

  • User enters registration data and card data through stripe.
  • The form is validated for registration data.
  • If the form is valid, payment is processed.
  • If payment goes through, it's all good, the user is registered and moves on.
  • If the payment fails, i want to be able to raise a validation error on a hidden field of the form. Is that possible?

Here's a the form submission code:

def register():
form = RegistrationForm()
if form.validate_on_submit():

    user = User(
        [...]
    )

    db.session.add(user)

    #Charge
    amount = 10000

    customer = stripe.Customer.create(
        email=job.company_email,
        card=request.form['stripeToken']
    )
    try:

        charge = stripe.Charge.create(
            customer=customer.id,
            amount=amount,
            currency='usd',
            description='Registration payment'
        )
    except StripeError as e:
        ***I want to raise a form validation error here if possible.***

    db.session.commit()
    return redirect(url_for('home'))

return render_template('register.html', form=form)
Apothecary answered 7/11, 2013 at 8:45 Comment(0)
A
31

I solved it by manually appending errors to the field i wanted.

It looks like that

try:

    [...]
except StripeError as e:
    form.payment.errors.append('the error message')
else:
    db.session.commit()
    return redirect(url_for('home'))
Apothecary answered 7/11, 2013 at 11:27 Comment(3)
The solution is working for me for StripeError, but I'm also geocoding with Google and then trying to raise an error using the form.field.errors.append('') method, but the error won't show up.Posticous
The problem was that adding errors doesn't stop the rest of the code from executing (I had a redirect at the end). I added additional code to check if the form still had errors before redirecting.Posticous
If you get "AttributeError: 'tuple' object has no attribute 'append'", see https://mcmap.net/q/1017867/-flask-self-errors-append-attributeerror-39-tuple-39-object-has-no-attribute-39-append-39Wrongdoer
P
2

on your wtform itself you can add a method prefixed with validate_ in order to raise an exception.

class RegistrationForm(Form):
  amount = IntegerField('amount', validators=[Required()])

  validate_unique_name(self, field):
    if field.data > 10000:
      raise ValidationError('too much money')

in my case I used it like so to validate that a user was not in the database already:

class Registration(Form):
  email = StringField('Email', validators=[Required(), Email()]) # field for email
  # ...
  def validate_email(self, field): # here is where the magic is
    if User.query.filter_by(email=field.data).first(): # check if in database
      raise ValidationError("you're already registered")
Paling answered 2/6, 2014 at 14:48 Comment(1)
Isn't this approach prone to a race condition?Lightheaded

© 2022 - 2024 — McMap. All rights reserved.