Форма колбы для петли - PullRequest
       36

Форма колбы для петли

0 голосов
/ 05 ноября 2019

Я пытаюсь сделать несколько обновлений для модели базы данных через одну форму фляги. По сути, я хочу отобразить вопросы для теста, а затем попросить пользователя вставить ответы для теста, а затем взять все отдельные ответы и обновить каждую соответствующую модель db.Model, указанную ниже.

Теперь у меня есть следующее:

Форма:

class InputStudentTestForm(FlaskForm):
    answer = StringField('Answer', validators=[DataRequired()])
    submit = SubmitField('Submit Answers')

Страница:

{% extends "base.html" %}

{% block content %}
  <h1>{{ test.name }}</h1>
  <form action="" method="post" >
    {{ form.hidden_tag() }}
      {% for q in questions %}
      <p>
        {{ q.text }} <br>
        {{ form.answer }}
      </p>

      {% endfor %}
      <p>
        {{ form.submit() }}
      </p>
  </form>

{% endblock %}

Маршрутизация:

@app.route('/input_answer/<testname>', methods=['GET', 'POST'])
def input_test_answer(testname):
    test = Test.query.filter_by(name=testname).first_or_404()
    questions = test.questions.all()
    form = InputStudentTestForm()
    if form.validate_on_submit():
        i = 0
        for value in form.data:
            q = questions[i]
            a = Student_Answers(current_user, test, q)
            a.add_response(value)
            db.session.add(a)
            db.session.commit()
            i = i + 1
        flash('You have just added new test responses')
        return redirect(url_for('index'))

    return render_template('input_test_answers.html', test=test, questions=questions, form=form)

Модель:

class Student_Answers(db.Model):

    user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=True, primary_key=True)
    test_id = db.Column(db.Integer, db.ForeignKey('test.id'), primary_key=True)
    question_id = db.Column(db.Integer, db.ForeignKey('question.id'), primary_key=True)
    student_option = db.Column(db.String(1))

    db.UniqueConstraint('user_id', 'test_id', 'question_id')
    db.relationship('User', uselist=False, backref='student_answers', lazy='dynamic')
    db.relationship('Test', uselist=False, backref='student_answers', lazy='dynamic')
    db.relationship('Question', uselist=False, backref='student_answers', lazy='dynamic')

    def add_response(self, answer):
        if not self.is_response(answer):
            self.student_option = answer

    def remove_response(self,answer):
        if self.is_response(answer):
            self.student_option = ''

    def is_response(self, answer):
        return self.student_option == answer

    def __init__(self, user, test, question):
        self.user_id = user.id
        self.test_id = test.id
        self.question_id = question.id

    def __repr__(self):
        return '<Student_Answer {}>'.format(self.student_option)

Но когда пользователь отправляет данные, я получаю уникальный сбой ограничения, так как Student_Answers обновляется с параметрами (1,1,1 'ответ').

Я думаю, что сбой происходит из-за того, что ответ учащегося должен состоять из одного символа, однако я не уверен, откуда берется строка 'answer' из form.data. Любая помощь будет отличной! Благодарю.

Редактировать: я пытаюсь реализовать подход динамической формы и получаю ошибку UnboundField. Вот обновленный код:

Форма:

def DynamicTestForm(questions, *args, **kwargs):
    class TestForm(FlaskForm):
        pass

    for name, value in questions.items():
        setattr(TestForm, name, value)

    return TestForm(*args, **kwargs)

Маршрут:

def input_test_answer(testname):
    test = Test.query.filter_by(name=testname).first_or_404()
    questions = test.questions.all()
    questions_as_field = {}
    for q in questions:
        p = field.SelectField('{}' .format(q.text), choices=[('A', 'A'), ('B', 'B'), ('C', 'C'), ('D', 'D')], validators=[DataRequired()])
        questions_as_field.update(p)

    form = DynamicTestForm(questions_as_field)
    if form.validate_on_submit():
        i = 0
        for value in form.data.values():
            a = Student_Answers.query.filter_by(user_id=current_user.id,test_id=test.id, question_id=q.id).one()
            if not a.is_response(str(value)):
                a.student_option = str(value)
            i = i + 1
        db.session.commit()
        flash('You have just added new test responses')
        return redirect(url_for('user', username=current_user.name))

и Страница:

{% extends "base.html" %}

{% block content %}
  <h1>{{ test.name }}</h1>
  <form action="" method="post" >
    {{ form.hidden_tag() }}
      {% for field in form %}
      <p>
        {{ field.label }} <br>
        {{ field() }}
      </p>

      {% endfor %}
      <p>
        {{ form.submit() }}
      </p>
  </form>

{% endblock %}

Но на этом этапе, Я получаю ошибку UnboundField, и я не очень уверен, почему.

1 Ответ

0 голосов
/ 06 ноября 2019

При использовании метода динамической формы я бы попробовал что-то вроде этого:

def DynamicTestForm(questions, *args, **kwargs):
    class TestForm(FlaskForm):
        pass

    for name, value in questions.items():
        setattr(TestForm, name, value)

    return TestForm(*args, **kwargs)


questions = {
    'question_1': fields.StringField('Question 1', description='The quick brown fox jumps over which lazy animal?'),
    'question_2': fields.StringField('Question 2', description='How many gigawatts does it take to go Back to the Future?')
}

f = DynamicTestForm(questions)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...