Wednesday 11 November 2020

How to display constraint errors from form in JSON using Flask-SQL Alchemy?

Right now, my project accepts user information from a form and returns the information as a POST request in JSON. The created user is also saved into the database. That is exactly what I want to do, however if the user inputs information that doesn't satisfy its constraint, I would like the end route to list JSON showing the errors. For example:

{
  "errors": {
    "color": [
      "Invalid value, must be one of: red, blue, yellow"
    ],
    "email": [
      "This field is required."
    ]
  }
}

I thought you could create something in the model class to handle these errors when constraints aren't satisfied. However, I can't find anything about this in the Flask-SQL Alchemy documentation or searching around online. Right now if the user types in the wrong input type (i.e. letters in the year field), a sqlalchemy.exc.DataError is shown along with bunch of tracebacks. This also occurs if a user's input is over the field's character limit. Also, when an input field is skipped, it just shows "" in the field in the created JSON rather than stating "This field is required." How would I create the above JSON to show these errors? My code is below

"""app.py"""

from flask import Flask, render_template, redirect, session, request, jsonify
from flask_debugtoolbar import DebugToolbarExtension
from werkzeug.exceptions import Unauthorized

from models import *

app = Flask(__name__)

app.config['SQLALCHEMY_DATABASE_URI'] = "postgres:///database_example"
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
app.config['SQLALCHEMY_ECHO'] = True
app.config['SECRET_KEY'] = "shhhhh"
app.config['DEBUG_TB_INTERCEPT_REDIRECTS'] = False

connect_db(app)
db.drop_all()
db.create_all()

toolbar = DebugToolbarExtension(app)


@app.route("/")
def homepage():
    """Show homepage."""
    return redirect("/api")

@app.route("/api", methods=["GET", "POST"])
def json_api():
    """JSON API Endpoint"""
    if request.method == "POST":
        user = User(
            name = request.form["name"], 
            year = request.form["birth_year"],
            email = request.form["email"],
            color = request.form["color"],
        )
        
        db.session.add(user)
        db.session.commit()

        user_dict = user.to_dict()
        return jsonify(user_dict)
        # return jsonify(user_dict)

    else:
        return render_template("index.html")

######################## """ models.py """##########################

from flask_sqlalchemy import SQLAlchemy

db = SQLAlchemy()


class User(db.Model):
    """User."""

    __tablename__ = "users"

    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    name = db.Column(db.String(50), nullable=False)
    email = db.Column(db.String(50), nullable=False)
    year = db.Column(db.Float(4), nullable=False)
    color = db.Column(db.String(20), nullable=False)

    def to_dict(self):
        """Serialize user to a dict of user info."""

        return {
            "id": self.id,
            "name": self.name,
            "email": self.email,
            "year": self.year,
            "color": self.color,
        }


def connect_db(app):
    """Connect to database."""

    db.app = app
    db.init_app(app)

######################### """ index.html """ ##########################

<!doctype html>
<html>
<head>
  <title>Title</title>
  <script src="https://unpkg.com/jquery"></script>
</head>
<body>

<form id="form" method="POST">
  <div>Name: <input id="name" name="name"> <b id="name-err"></b> </div>
  <div>Birth Year: <input id="year" name="birth_year"> <b id="year-err"></b> </div>
  <div>Email: <input id="email" name="email"> <b id="email-err"></b> </div>
  <div>Color: <input id="color" name="color"> <b id="color-err"></b> </div>
  <button>Submit</button>
</form>



</body>
</html>


from How to display constraint errors from form in JSON using Flask-SQL Alchemy?

No comments:

Post a Comment