1
votes

I'm building a system which allows admin users to add "questions" to the database. Each type of question has a WTForms object associated with it. To display a page, I loop over all questions and generate a form consisting of form fields for each question.

class TextQuestionForm(Form):
  value = TextField("Value", validators=[])

class Question(db.Model):
  # sqlAlchemy model using single table inheritance
  def field_name(self):
    return "question_%s" % self.id

class TextQuestion(Question):
  form = TextQuestionForm


def get_form(page_id):
  questions = Question.query.filter(Question.page_id == page_id).all()

  class F(Form):
    pass

  for q in questions:
    setattr(F, q.field_name(), FormField(q.form))

  return F()

This works well for simple cases where all validation is the same for a given question type, but I need to provide configurable validation options for each instance of Question, for example imagine if my Question model was extended:

class Question(db.Model):
  # ... other fields
  min_length = db.Column(db.Integer, nullable=True)
  max_length = db.Column(db.Integer, nullable=True)

What would be the appropriate way to get a WTForms length validator on to the value field within my Form field, given that min/max lengths would be different (or missing) for each question?

1
I mean I think this is a bit trickier than you make it out to be. Firs t the fields would be better as static class attributes otherwise you'd be storing them in the db all the time and they'd be subject to sql manipulation. Second when the raw form data came in you'd need to know what Question class that form data referred to. You might be best off just submitting an additonal field that cued the a custom field validator as to some of the special processing fields for that type of question. Then you would only need one question model. - nsfyn55

1 Answers

0
votes

To have complete control over the validation you can create a custom field inheriting TextField and redefine the pre_validate method

def pre_validate(self, form=None)

and inside that function you can do all the checks you want

http://wtforms.simplecodes.com/docs/0.6/fields.html#wtforms.fields.Field.pre_validate