Flask is a microframework for Python that is ideal for creating web applications and APIs. Its simplicity and flexibility make it an excellent choice for both beginners and experienced developers. In this article, we will analyze how to create a simple but full-featured API using Flask.
What is an API and why do you need it
An API (Application Programming Interface) is a set of rules and tools that allow different programs to interact with each other. The RESTful API uses HTTP requests to perform CRUD (Create, Read, Update, Delete) operations on data. Modern web applications are often divided into frontend and backend, where the API serves as a bridge between them.
Preparing the environment
Before we start, we need to install Flask. It is recommended to use a virtual environment to isolate project dependencies:
python -m venv venv
source venv/bin/activate # for Linux/Mac
venv\Scripts\activate # for Windows
pip install flaskCreating a basic API
Let's start by creating the simplest Flask application. Create the app.py file:
from flask import Flask, jsonify, request
app = Flask(__name__)
# Temporary data storage
books = [
{'id': 1, 'title': 'Clean code', 'author': 'Robert Martin'},
{'id': 2, 'title': 'Python. To the heights of mastery', 'author': 'Luciano Ramallo'}
]
@app.route('/')
def home():
return jsonify({'message': 'Welcome to the API library!'})
if __name__ == '__main__':
app.run(debug=True)Run the application with the python app.py command, and the server will be available at http://127.0.0.1:5000/.
Implementation of CRUD operations
Now let's add endpoints for working with books.
Getting all books (GET)
@app.route('/api/books', methods=['GET'])
def get_books():
return jsonify({'books': books, 'count': len(books)})Getting a book by ID (GET)
@app.route('/api/books/<int:book_id>', methods=['GET'])
def get_book(book_id):
book = next((book for book in books if book['id'] == book_id), None)
if book:
return jsonify(book)
return jsonify({'error': 'Book not found'}), 404Create a new book (POST)
@app.route('/api/books', methods=['POST'])
def create_book():
if not request.json or 'title' not in request.json:
return jsonify({'error': 'You must specify the name of the book'}), 400
new_book = {
'id': books[-1]['id'] + 1 if books else 1,
'title': request.json['title'],
'author': request.json.get('author', 'Unknown author')
}
books.append(new_book)
return jsonify(new_book), 201Update book (PUT)
@app.route('/api/books/<int:book_id>', methods=['PUT'])
def update_book(book_id):
book = next((book for book in books if book['id'] == book_id), None)
if not book:
return jsonify({'error': 'Book not found'}), 404
book['title'] = request.json.get('title', book['title'])
book['author'] = request.json.get('author', book['author'])
return jsonify(book)Delete book (DELETE)
@app.route('/api/books/<int:book_id>', methods=['DELETE'])
def delete_book(book_id):
global books
books = [book for book in books if book['id'] != book_id]
return jsonify({'message': 'Book deleted successfully'})Error handling
Let's add error handlers for more informative responses:
@app.errorhandler(404)
def not_found(error):
return jsonify({'error': 'Resource not found'}), 404
@app.errorhandler(500)
def internal_error(error):
return jsonify({'error': 'Internal server error'}), 500API testing
For testing, you can use curl, Postman, or the Python library requests:
# Get all books
curl http://127.0.0.1:5000/api/books
# Create a new book
curl -X POST http://127.0.0.1:5000/api/books \
-H "Content-Type: application/json" \
-d '{"title":"Perfect Code","author":"Steve McConnell"}' Update book
curl -X PUT http://127.0.0.1:5000/api/books/1 \
-H "Content-Type: application/json" \
-d '{"title":"Clean Code (new edition)"}'# Delete book
curl -X DELETE http://127.0.0.1:5000/api/books/2Adding validation
For more reliable data validation, you can use the flask-marshmallow library:
from flask_marshmallow import Marshmallow
ma = Marshmallow(app)
class BookSchema(ma.Schema):
class Meta:
fields = ('id', 'title', 'author')
book_schema = BookSchema()
books_schema = BookSchema(many=True)Database connection
For real applications, it is worth using a database. Let's install Flask-SQLAlchemy:
pip install flask-sqlalchemyExample of a book model with SQLAlchemy:
from flask_sqlalchemy import SQLAlchemy
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///books.db'
db = SQLAlchemy(app)
class Book(db.Model):
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(200), nullable=False)
author = db.Column(db.String(100))
def to_dict(self):
return {
'id': self.id,
'title': self.title,
'author': self.author
}Adding CORS
If your API is used by a frontend application, you need to configure CORS:
pip install flask-corsfrom flask_cors import CORS
CORS(app)
Safety and best practices
When developing an API, it is important to keep security in mind. Use environment variables to store sensitive data, implement authentication through JWT tokens, limit the number of requests (rate limiting), validate all incoming data, and use HTTPS in production.
It is also recommended to organize the project structure by dividing the code into modules: create separate files for models, routes and configurations. Use Blueprint to group related endpoints, which makes the code more maintainable and scalable.
Deploy API
To deploy a Flask application in production, use a WSGI server such as Gunicorn:
pip install gunicorn
gunicorn -w 4 app:appPopular deployment platforms: Heroku, DigitalOcean, AWS, or traditional VPS with nginx as a reverse proxy.
Conclusion
We have created a full-fledged RESTful API with Flask, which includes all the basic CRUD operations, error handling and data validation. Flask provides a minimal but powerful basis for creating APIs of any complexity. The next steps could be adding authentication, documenting the API with Swagger, writing unit tests, and optimizing performance.
Want to learn more about Python and web development?
Appendix Code offers structured courses in Python, JavaScript, API, and many other technologies. The training is based on practical examples with step-by-step explanations.
Join our Telegram channel, where you will find useful materials, programming tips, and support from an active community of developers ready to help at any stage of your training!
