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 isNone
.
print(form.lesson.choices)
the result is thechoices[(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 thechoices[]
.
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>