-1

The Situation:

I have 3 forms on the same page and within these three forms, I have set up ajax calls to fetch the available classes depending on choices within the forms, thus allowing them to select a lesson before submitting. I have done this in another section of the app and it seems to be working, however here it isn't.

Before getting to the errors, here is the code. So I have the following route:

The Code:

@bp.route('/edit_student/<academy>/<name>', methods=['GET','POST'])
@login_required
@group_required(['Master', 'Upper Management', 'Management', 'Admin'])
def edit_student(name, academy):

    academy = Academy.query.filter_by(name=academy).first()
    student = Student.query.filter_by(name=name).filter_by(academy_id=academy.id).first()
    current_lesson = Lessons.query.filter_by(id=student.class_id).first()
    length_of_class = LengthOfClass.query.filter_by(id=current_lesson.length_of_class).first()
    type_of_class = TypeOfClass.query.filter_by(id=current_lesson.type_of_class).first()
    options_121 =['121-General English', '121-Exam Class', '121-Business English', '121-Children', 'In-Company-121']
    step = None

    if not current_user.is_master() and current_user.position != "Upper Management":
        if current_user.academy_id != academy.id:
            flash('You can only remove people from your own academy.')
            return redirect(url_for('students.student_profile', name=student.name, academy=academy.name))

    if type_of_class.name == 'Group General English':
        step = Step.query.filter_by(id=student.step_id).first()

    form = EditStudentForm(obj=student.id)
    form2 = AdditionalClassForm(obj=student.id)
    form3 = AdditionalClassForm2(obj=student.id)

    # Fill current form details
    form.name.data = student.name
    form.phone.data = student.phone
    form.email.data = student.email
    form.comment.data = student.comment
    form.lengthofclass.data = length_of_class.name
    form.academy.data = academy.name
    form.typeofclass.data = type_of_class.name
    if step:
        form.step.data = step.name
    form.lesson.choices = [(current_lesson.id, '{} Students: {}/8 {}'.format(current_lesson.name, current_lesson.amount_of_students, current_lesson.time))]

    if student.student_on_class:

        link = Studentonclass.query.filter_by(id=student.student_on_class).first()
        lesson = Lessons.query.filter_by(student_on_class=link.id).first()
        acad = Academy.query.filter_by(id=lesson.academy_id).first()
        length_of = LengthOfClass.query.filter_by(id=lesson.length_of_class).first()
        type_of = TypeOfClass.query.filter_by(id=lesson.type_of_class).first()

        if type_of.name == 'Group General English':
            step_additional = Step.query.filter_by(id=lesson.step_id).first()
            form2.step.data = step_additional.name

        form2.lengthofclass.data = length_of.name
        form2.academy.data = acad.name
        form2.typeofclass.data = type_of.name
        form2.lesson_.choices = [(lesson.id, '{} Students: {}/8 {}'.format(lesson.name, lesson.amount_of_students, lesson.time))]

    if student.student_on_class2:

        link = Studentonclass.query.filter_by(id=student.student_on_class2).first()
        lesson = Lessons.query.filter_by(student_on_class=link.id).first()
        acad = Academy.query.filter_by(id=lesson.academy_id).first()
        length_of = LengthOfClass.query.filter_by(id=lesson.length_of_class).first()
        type_of = TypeOfClass.query.filter_by(id=lesson.type_of_class).first()

        if type_of.name == 'Group General English':
            step_additional = Step.query.filter_by(id=lesson.step_id).first()
            form3.step.data = step_additional.name

        form3.lengthofclass.data = length_of.name
        form3.academy.data = acad.name
        form3.typeofclass.data = type_of.name
        form3.lesson3.data = [(lesson.id, '{} Students: {}/8 {}'.format(lesson.name, lesson.amount_of_students, lesson.time))]


    if form.validate_on_submit():
        if form.typeofclass.data == 'Group General English':
            print(form.lesson.data)
            print(form.lesson.choices)
            if form.lesson.data == 'None':
                flash('You must have a lesson value')
                return redirect(url_for('students.edit_student', name=student.name, academy=academy.name))
            if form.lesson.data == None:
                flash('You must have a lesson value')
                return redirect(url_for('students.edit_student', name=student.name, academy=academy.name))

            if student.name != form.name.data:
                student.name = form.name.data
            if student.phone != form.phone.data:
                student.phone = form.phone.data
            if student.email != form.email.data:
                student.email = form.email.data
            if student.comment != form.comment.data:
                student.comment = form.comment.data
            if academy.name != form.academy.data:
                new_academy = Academy.query.filter_by(name=form.academy.name).first()
                student.academy_id = new_academy.id
            if current_lesson.id != form.lesson.data:
                new_lesson = Lessons.query.filter_by(id=form.lesson.data).first()
                student.class_id = new_lesson.id
            if type_of_class.name != form.typeofclass.data:
                if form.typeofclass.data == 'Group General English':
                    student.step_id = new_lesson.step_id
            if step:
                if step.name != form.step.data:
                    step = Step.query.filter_by(name=form.step.data).first()
                    student.step_id = step.id
            student.user_id = current_user.id


        elif form.typeofclass.data in options_121:
            # Create 121 class here
            lesson_name = get_name(name=form.name.data, academy=academy.id, types=form.typeofclass.data, companyname=form.companyname.data)


        if form2.academy.data and form2.typeofclass.data and form2.lengthofclass.data and form2.lesson_.data:
            if form2.typeofclass.data == 'Group General English':
                if form2.lesson_.data == 'None':
                    flash('You must have a lesson in order to add an additional lesson')
                    return redirect(url_for('students.edit_student', name=student.name, academy=academy.name))
                if step:
                    if form2.step.data != step.name:
                        if int(form2.step.data) <= step.name - 3 or int(form2.step.data) >= step.name + 3:

                            flash('You cannot place a student in such a different step to their level')
                            return redirect(url_for('students.edit_student', name=student.name, academy=academy.name))

                # handling additional classes
                acad = Academy.query.filter_by(name=form2.academy.data).first()
                length_of = LengthOfClass.query.filter_by(name=form2.lengthofclass.data).first()
                type_of = TypeOfClass.query.filter_by(name=form2.typeofclass.data).first()
                additional_lesson = Lessons.query.filter_by(id=form2.lesson_.data).first()

                if acad.name != 'Online' and acad.name != academy.name:
                    flash('Student can only be part of two different academy classes if one academy is online!')
                    return redirect(url_for('students.edit_student', name=student.name, academy=academy.name))

                if type_of.name == type_of_class.name and additional_lesson.id == current_lesson.id:
                    flash('You cannot add them to a second class to the same class')
                    return redirect(url_for('students.edit_student', name=student.name, academy=academy.name))


                if additional_lesson.student_on_class:
                    link = Studentonclass.query.filter_by(id=additional_lesson.student_on_class).first()
                    student.student_on_class = link.id
                    additional_lesson.amount_of_students = additional_lesson.amount_of_students + 1
                    db.session.commit()
                else:
                    link = Studentonclass()
                    db.session.add(link)
                    db.session.commit()

                    additional_lesson.student_on_class = link.id
                    student.student_on_class = link.id
                    additional_lesson.amount_of_students = additional_lesson.amount_of_students + 1

                    db.session.commit()
            elif form2.typeofclass.data in options_121:
                # Create 121 class here
                lesson_name = get_name(name=form.name.data, academy=academy.id, types=form2.typeofclass.data, companyname=form2.companyname_.data)


        if form3.academy.data and form3.typeofclass.data and form3.lengthofclass.data and form3.lesson3.data:

            if form3.typeofclass.data == 'Group General English':

                if form3.lesson3.data == 'None':
                    flash('You must have a lesson in order to add second additional lesson.')
                    return redirect(url_for('students.edit_student', name=student.name, academy=academy.name))
                if form3.lesson3.data == None:
                    flash('You must have a lesson in order to add second additional lesson.')
                    return redirect(url_for('students.edit_student', name=student.name, academy=academy.name))

                acad = Academy.query.filter_by(name=form3.academy3.data).first()
                length_of = LengthOfClass.query.filter_by(name=form3.lengthofclass3.data).first()
                type_of = TypeOfClass.query.filter_by(name=form3.typeofclass3.data).first()
                additional_lesson = Lessons.query.filter_by(id=form3.lesson3.data).first()

                if acad.name != 'Online' and acad.name != academy.name:
                    flash('Student can only be part of two different academy classes if one academy is online!')
                    return redirect(url_for('students.edit_student', name=student.name, academy=academy.name))

                if type_of.name == type_of_class.name and additional_lesson.id == current_lesson.id:
                    flash('You cannot add them to a second class to the same class')
                    return redirect(url_for('students.edit_student', name=student.name, academy=academy.name))

                if type_of.name == form2.typeofclass.name and additional_lesson.id == form2.lesson_.data:
                    flash('You cannot add them to a second class to the same class')
                    return redirect(url_for('students.edit_student', name=student.name, academy=academy.name))

                if step:
                    if form3.step.data != None and form3.step.data != step.name or form2.step.data != None and form3.step.data != form2.step.data:
                        if int(form3.step.data) <= step.name - 3 or int(form3.step.data) >= step.name + 3:
                            flash('Please Keep the step levels in all classes as close to eachother as possible.')
                            return redirect(url_for('students.edit_student', name=student.name, academy=academy.name))


                if additional_lesson.student_on_class2:
                    link = Studentonclass2.query.filter_by(id=additional_lesson.student_on_class2).first()
                    student.student_on_class2 = link.id
                    additional_lesson.amount_of_students = additional_lesson.amount_of_students + 1
                    db.session.commit()
                else:
                    link = Studentonclass2()
                    db.session.add(link)
                    db.session.commit()

                    additional_lesson.student_on_class2 = link.id
                    student.student_on_class2 = link.id
                    additional_lesson.amount_of_students = additional_lesson.amount_of_students + 1
                    db.session.commit()

            elif form3.typeofclass.data in options_121:
                # Create 121 class here
                lesson_name = get_name(name=form.name.data, academy=academy.id, types=form3.typeofclass3.data, companyname=form3.companyname3.data)


        db.session.commit()

        flash('Student Editted')

        return redirect(url_for('students.edit_student', name=student.name, academy=academy.name))

    return render_template('students/edit_student.html', title="Edit Student", form=form, form2=form2, form3=form3, student=student, student_id=student.id, academy=academy)

This is the route that is handling the displaying of the page and the handling of the form once submitted. Now as to how this is being handled, I have the following that sends the ajax call:

function run_ajax(form_id, lesson_name, lesson_class, stepfield_id, examfield_id, kidfield_id, agefield_id, type_of_class) {
    lesson_class.show('slow')
    lesson_name.show('slow')
    // if form_id = additional turn url to one route or the other create different route for each ajax call
    if (form_id === '#form1') {
        var url_is = "/get_classes_edit/" + {{student_id | safe}}
    } else if (form_id === '#form2') {
        var url_is = "/get_classes_add1"
    } else if (form_id === '#form3') {
        var url_is = "/get_classes_add2"
    }
    var form = $(form_id).serialize();
    if (step_options.includes(type_of_class) && stepfield_id.val() != 'None') {
        $.ajax(
            {
            type: 'POST',
            url: url_is,
            data: $(form_id).serialize(),
            context: form,
            success: function(selectOptions){
                lesson_name.empty();
                console.log(selectOptions.length)
                if (selectOptions.length == 0) {
                    lesson_name.append(
                        $("<option></option>")
                        .attr("value", 'None')
                        .text('No classes of this type are available please create a class.'))
                }
                for (var i = 0; i < selectOptions.length; i++){
                    lesson_name.append(
                        $("<option></option>")
                        .attr("value", selectOptions[i]['lesson_id'])
                        .text(selectOptions[i]['lesson_name'] + ' Students: ' + selectOptions[i]['amount_of_students'] + '/8' + ' ' + selectOptions[i]['lesson_time']))
                }
            }
        });
    } else if (exam_options.includes(type_of_class) && examfield_id.val() != 'None'){
        alert('Please select the level')
    } else if (kids_options.includes(type_of_class) && kidfield_id.val() != 'None' || agefield_id.val() != 'None'){
        alert('Please select the level')
    }
}

This ajax call is called with the line:

run_ajax('#form2', $('#lesson_name2'), $('.lesson_'), $('#step2'),  $('#exam2'), $('#kid2'), $('#agerange2'), type_of2)

Now with these, each of the urls is handled by a route set up similarly to this:

@bp.route('/get_classes_edit/<student>', methods=['POST'])
def get_classes_edit(student):

    student = Student.query.filter_by(id=student).first()
    form = EditStudentForm(obj=student.id)

    if form.submit():
        academy = Academy.query.filter_by(name=form.academy.data).first()
        length_of = LengthOfClass.query.filter_by(name=form.lengthofclass.data).first()
        type_of_class = TypeOfClass.query.filter_by(name=form.typeofclass.data).first()
        step = Step.query.filter_by(name=form.step.data).first()

        choices = []
        if form.typeofclass.data == 'Group General English':

            lessons = Lessons.query.filter_by(academy_id=academy.id)\
                .filter_by(length_of_class=length_of.id)\
                .filter_by(type_of_class=type_of_class.id)\
                .filter_by(step_id=step.id).all()

            for i in lessons:
                if i.amount_of_students < 8:
                    choice_final = {
                        'lesson_id': i.id,
                        'lesson_name': i.name,
                        'amount_of_students': i.amount_of_students,
                        'lesson_time': i.time
                    }
                    choices.append(choice_final)

            # return none so that can display message
    return jsonify(choices)

The Errors:

With this there are no traceback errors at all, but rather performance errors in that it isn't working as expected. I have tried printing multiple things to identify what is going on inside.

Now when I print:

print(form.lesson.data) the result is None.

print(form.lesson.choices) the result is the choices[(6, 'STA-1'),(8, 'SMA-2')].

print(form.lesson.raw_data) the result is [].

This is different to the one working, as I am receiving this from the one that is working:

print(form.lesson.data) the result is '6'.

print(form.lesson.choices) the result is the choices[].

The Entire idea in the ajax call is to set the id as the value in the tag within the selectfield and receive this via form.lesson.data in order to work with it, but instead I can read the choices but not the value?

The Question:

Why is the form.lesson.data returning None, when clearly it is able to read the data within the choices with the form.lesson.choices? Am I missing something? How can I get it to send the value through as this is working perfectly front-end with sending the calls and loading the results into the field as expected, but when submitting the form doesn't seem to be able to access the value set within the ajax call.

If you are curious, the working portion in another part of the web app which operates similarly is here:

The ajax call: https://dpaste.com/385NDRJPD

The handler: https://dpaste.com/27UZA9EA6

The route: https://dpaste.com/49579JGP3

Obviously this working example is a much simpler route that just handles a single form adding data to the database, while the route I have problems with is much larger and handles more operations.

I have been searching and came across this: Post values from an HTML form and access them in a Flask view

However this cannot be the case because the HTML rendered by my form display macro is:

<dt> <label class="lesson" for="lesson">Class</label></dt>
    <dd><select class="form-control lesson_name" id="lesson_name" name="lesson" style="width:33%;"><option value="6">STA - 1 Students: 1/8 14:00:00</option></select>

    </dd>
<br>

1 Answers1

0

So the solution to this was I was trying to send the different forms to the same route to be handled without using ajax or anything and it came down that i used the action attribute of the form to send it to different routes in order to handle each form individually