Part 2: Building a Flask RESTful API
This is the second of three posts about building a JSON API with Flask. Part 1 arrived yesterday and part 3 is arriving tomorrow.
In the previous post we learned how to serialize SQLAlchemy models to/from JSON. Now let’s use that to build a RESTful JSON API with Flask.
What is a RESTful API
A RESTfu API is a website that conforms to the REST conventions by allowing CRUD operations on resources. Resources are the noun you are fetching or updating, for ex: Users or Goals. Unlike GraphQL, where every resource shares the same url endpoint, RESTful APIs use a different url for each resource. That means Users would be at yoursite.com/api/users
and Goals at yoursite.com/api/goals
. When you visit yoursite.com/api/users
in your browser, it should return JSON with a list of users.
A RESTful API with Flask
Here’s a simple Flask API that always returns an empty list of Users:
from flask import Flask app = Flask(__name__) @app.route("/api/users") def users(): return "[]" if __name__ == "__main__": app.run()
Let’s improve that to return a list of users from our database using SQLAlchemy.
from flask import Flask, json from flask_sqlalchemy import SQLAlchemy app = Flask(__name__) db = SQLAlchemy(app) class User(BaseModel): id = db.Column(UUID(), primary_key=True, default=uuid.uuid4) username = db.Column(db.String(), nullabe=False, unique=True) password = db.Column(db.String()) _default_fields = ["username"] _hidden_fields = ["password"] @app.route("/api/users") def users(): return json.dumps([user.to_dict() for user in User.query.all()]) if __name__ == "__main__": app.run()
The BaseModel
class is the one we created in Part 1: SQLAlchemy Models as JSON.
Visiting yoursite.com/api/users
in your browser you should see:
[{"id": "488345de-88a1-4c87-9304-46a1a31c9414", "username": "zzzeek"}]
Following this pattern, we create GET
resources for all our SQLAlchemy models.
Updating Models with PUT method
Most APIs support more than just GET
requests. To update Users let’s add a PUT
method that accepts JSON and updates a User’s attributes. This example depends on WTForms and WTForms-JSON libraries for input validation.
@app.route("/api/users/<string:user_id>", methods=['PUT']) def users_update(user_id): user = User.query.get(user_id) form = UserForm.from_json(request.get_json()) if not form.validate(): return jsonify(errors=form.errors), 400 user.from_dict(**form.data) db.session.commit() return jsonify(user=user.to_dict())
Sending {"username": "zoe"}
to yoursite.com/api/users/488345de-88a1-4c87-9304-46a1a31c9414
updates User with a new username. We validate user input with WTForms and control which database columns are readable and writable with our BaseModel SQLAlchemy class.
Conclusion
Now that we’re building APIs with Flask, it’s time to add extra features with some useful decorators and more BaseModel
helper methods. Continue reading Part 3: Flask API Decorators and Helpers.
Published on Web Code Geeks with permission by Alan Hamlett, partner at our WCG program. See the original article here: Part 2: Building a Flask RESTful API Opinions expressed by Web Code Geeks contributors are their own. |