10

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)
applechief
  • 6,615
  • 12
  • 50
  • 70

2 Answers2

29

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'))
applechief
  • 6,615
  • 12
  • 50
  • 70
  • 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. – Patrick Yan Oct 16 '14 at 18:23
  • 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. – Patrick Yan Oct 16 '14 at 20:29
  • 2
    If you get `"AttributeError: 'tuple' object has no attribute 'append'"`, see https://stackoverflow.com/a/22889381/328817 – Sam Feb 07 '19 at 12:45
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")
corvid
  • 10,733
  • 11
  • 61
  • 130