0

i get an error 400 when posting. i'm using flask and sqlalchemy in the backend, and pretty straightforward javascript & jquery here is the JS:

    $.ajax({
        url: "/create",
        type: "POST",
        data: {
          question: question,
          answer1: answer1,
          answer2: answer2,
          answer3: answer3,
          answer4: answer4,
          answer5: answer5,
          answer6: answer6,
          congress: congress,
          session: session,
          date: date,
          lecture: lecture,
          correct: correct
        },
        success: function(){
            console.log("sent");
        }, error: function(xhr, textStatus, error){
            console.log(xhr.statusText);
            console.log(textStatus);
            console.log(error);
            }
    });
}

and here is the Flask code:

@app.route('/create', methods=['GET', 'POST'])
def cre():
post = QuestionClass(congress=str(request.form['congress']), 
session=str(request.form['session']),
                     date=str(request.form['date']), 
lecture=str(request.form['lecture']),
                     question=str(request.form['question']), 
answer1=str(request.form['answer1']),
                     answer2=str(request.form['answer2']), answer3=str(request.form['answer3']),
                     answer4=str(request.form['answer4']), answer5=str(request.form['answer5']),
                     )

engine = create_engine(sqlite:///DB.db', echo=True)
Session = sessionmaker(bind=engine)
sqlsession = Session()
sqlsession.add(post)
sqlsession.commit()
return 1

and i can't for the life of me figure out what's wrong...

Benny
  • 695
  • 2
  • 6
  • 19
  • Just wondering about your key : values, for example question: question, I assume the value (after semicolon is a variable), what about the key? If its not a variable, then what you are likely sending is Undefined: question, which flask will not understand. Would you try to make the keys a string? like "question": question and let me know if it works – Moses N. Njenga May 04 '18 at 05:40

2 Answers2

0

I also had a thorough look, but couldn't find anything obvious. I made a small working example, which does exactly what you hope it should be doing. Try adding stuff to the example till you break it.

from flask import Flask, render_template_string, request, jsonify, url_for

app = Flask(__name__)


@app.route('/', methods=['GET', 'POST'])
def index():
    if request.method == 'POST':
        info = request.form['question']
        print(info)
        return jsonify({'what_you_sent': info})

    return render_template_string('''
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>title</title>
</head>
<body>
<script src="https://code.jquery.com/jquery-3.3.1.js"></script>
<div></div>
<script>
 $.ajax({
        url: "/",
        type: "POST",
        data: {
          question: 'hello?',
          answer1: 'hi',
         },
        success: function(data){
            alert(data.what_you_sent);},
        error: function(xhr, textStatus, error){
            alert('such error')}
    });
</script>
</body>
</html>
''')


app.run()

Just a general tip when debugging 400 errors, just access the form elements one by one instead of directly applying them to a model or whatever, it's easier to spot them like that.

like:

print(request.form['question'])
print(request.form['answer1'])
etc...

Also clean your browser cache just in case.

Joost
  • 3,609
  • 2
  • 12
  • 29
0

As I have mentioned in my comment what the data object represents is a json object and unlike javascript objects, the keys must be strings see this ref

Change your data object to (am assuming your values are valid JSON data type (string, number, object, array, boolean or null))

EDIT I was answering this question and realized the main problem could be that your data was url-encoded by jquery. If you stringify it like below, it should work. Try it on your original code

data: JSON.stringify({
          "question": question,
          "answer1": answer1,
          "answer2": answer2,
          "answer3": answer3,
          "answer4": answer4,
          "answer5": answer5,
          "answer6": answer6,
          "congress": congress,
          "session": session,
          "date": date,
          "lecture": lecture,
          "correct": correct
        }),

Okay, I will make your flask a bit more complicated, but for a good cause. I will make a wtf form (you can make a normal form but I like the additional features of wtf like validation etc)

class QuestionForm(FlaskForm):
    question = StringField('question', [validators.InputRequired(message="Please enter a valid entry")])
    answer1 = StringField('answer1', [validators.InputRequired(message="Please enter a valid entry")])
    answer2 = StringField('answer2', [validators.InputRequired(message="Please enter a valid entry")])
    answer3 = StringField('answer3', [validators.InputRequired(message="Please enter a valid entry")])
    answer4 = StringField('answer4', [validators.InputRequired(message="Please enter a valid entry")])
    answer5 = StringField('answer5', [validators.InputRequired(message="Please enter a valid entry")])
    answer6 = StringField('answer6', [validators.InputRequired(message="Please enter a valid entry")])
    congress = StringField('congress', [validators.InputRequired(message="Please enter a valid entry")])
    session = StringField('session', [validators.InputRequired(message="Please enter a valid entry")])
    date = StringField('date', [validators.InputRequired(message="Please enter a valid entry")])
    lecture = StringField('lecture', [validators.InputRequired(message="Please enter a valid entry")])
    correct = StringField('correct', [validators.InputRequired(message="Please enter a valid entry")])

Be sure to make relvant imports if you go with wtf

from flask_wtf import FlaskForm
from wtforms import Form, BooleanField, StringField, IntegerField, validators, SelectField, TextAreaField, HiddenField

Then I will use werkzeug.datastructures to access the json data (i start with import, import the form as well if it is in a different file from forms import QuestionForm), then access all the values of the form. I am returning all the values in a string just to be sure I am receiving them, am sure you will know how to save to your database from there

from werkzeug.datastructures import MultiDict
@app.route('/create', methods=['POST'])
def cre():
    form_data = MultiDict(mapping=request.json)
    form = QuestionForm(form_data)
    if request.is_json:
        question= form.question.data
        answer1= form.answer1.data
        answer2= form.answer2.data
        answer3= form.answer3.data
        answer4= form.answer4.data
        answer5= form.answer5.data
        answer6= form.answer6.data
        congress= form.congress.data
        ssession= form.session.data
        date= form.date.data
        lecture= form.lecture.data
        correct= form.correct.data
    return str(question+' '+answer1+' '+answer2+' '+answer3+' '+answer4+' '+answer5+' '+answer6+' '+congress+' '+ssession+' '+date+' '+lecture+' '+correct)

You can add if form.validate_on_submit(): after the if request.is_json: if you wish to validate the data as per the validators you specify on the form

I am able to get a response with all the values I put in my json object. I am sure if you find this example one that can work for you, you will be able to debug from there (I used ssession because on my testing app i already have session defined)

Moses N. Njenga
  • 762
  • 1
  • 9
  • 19
  • @Benny have a look at a few additions to the answer and see if it will be useful. I am able to return all the values put in the json object from my view – Moses N. Njenga May 04 '18 at 14:44
  • Hi @Benny I have added an edit that I think will sort out the problem with your code. Raw json is usually url-encoded by jquery, try the edit I have added with your original code – Moses N. Njenga May 05 '18 at 20:15