简体   繁体   English

在WTForms中对动态大小的FieldList进行验证

[英]Validation on dynamically sized FieldList in WTForms

I am creating a quiz webapp using Flask and WTForms in which the user is shown a quiz which they can answer. 我正在使用Flask和WTForms创建一个测验web应用,其中向用户显示了一个他们可以回答的测验。 The questions for the quiz come from a DB and hence the form to let the users answer the quiz is dynamic. 测验的问题来自数据库,因此让用户回答测验的表格是动态的。 Here is how the form class looks like: 表单类如下所示:

class QuizForm(FlaskForm):
    answers = FieldList(RadioField('Correct Answer', choices=CHOICES,
                                   validators=[DataRequired()]),
                        min_entries=0)
    submit = SubmitField('Submit your answers')

Before I serve the form, I append entries to the field list as follows: 在提供表单之前,我将条目追加到字段列表中,如下所示:

questions = Question.query.all()
form = QuizForm()
for i, question in enumerate(questions):
    form.answers.append_entry()
    choices = [('1', question.option_a),
               ('2', question.option_b),
               ('3', question.option_c),
               ('4', question.option_d)]
    form.answers.entries[i].choices = choices

This works well and creates the form as I would expect. 这可以很好地工作并创建我所期望的形式。 But, I am not able to get validation to work where I want to make sure the user has answered all questions. 但是,我无法在想要确保用户已回答所有问题的地方进行验证。 This is how I am currently validating the form: 这是我当前验证表单的方式:

questions = Question.query.all()
form = QuizForm(request.form)
if request.method == 'POST':
    if form.validate() and len(form.answers.entries) == len(questions):
        # use form data

The problems I have are: 我遇到的问题是:

  • I would ideally want the validation to work just using form.validate() . 理想情况下,我希望仅使用form.validate()进行验证。
  • In the current approach, the values for field.errors are not set, and thus I can't show the user a message that a field is required right below the radio field containing the options for the question (using WTForms validation). 在当前方法中,未设置field.errors的值,因此我无法向用户显示一条消息,要求在包含问题选项的单选字段正下方需要一个字段(使用WTForms验证)。

The full code can be seen at github . 完整的代码可以在github上看到。

What is a good way to implement validation for this use case? 什么是实现此用例验证的好方法?

As commented further info in questions: stackoverflow.com/questions/50882720 and stackoverflow.com/questions/51048153 如评论中的其他问题信息:stackoverflow.com/questions/50882720和stackoverflow.com/questions/51048153

Personally I would use the dynamic form method to assign a unique name to each RadioField required so that the result would be similar to, for example if the form was statically created: 就个人而言,我将使用动态表单方法为所需的每个RadioField分配一个唯一的名称,以使结果类似于例如静态创建表单的情况:

class WebForm(FlaskForm):
    q_1 = RadioField('Q 1', validators=[InputRequired()], ...)
    q_2 = RadioField('Q 2', validators=[InputRequired()], ...)

Then the validators will definitely work as requested. 然后,验证器一定会按要求工作。

Failing that I suppose you could just write your own validator over your FieldList named answers . 如果做不到这一点,我想你可以只写自己的验证在你的FieldList中命名answers Here is an example of a custom validator catching an input field supposed to capture a full name and it breaks if it doesn't detect a space between names: 这是一个自定义验证器的示例,该验证器捕获了一个应该捕获全名的输入字段,并且如果它未检测到名称之间的空格,它将中断:

from wtforms.validators import ValidationError
class WebForm(FlaskForm):
    fullname = StringField('Input full name', validators=[])
    def validate_fullname(self, field):
        if ' ' not in field.data:
            raise ValidationError('Please give first and last name')

If you write your own validator on the FieldList you can perhaps loop through and check each has some data, but the more painful approach (in my opinion) is why I stated my preferred way of doing this. 如果您在FieldList上编写自己的验证器,则FieldList可以循环浏览并检查每个验证器是否有数据,但是(我认为)更痛苦的方法是为什么我声明了我的首选方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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