CHAPTER 13
Web Dev Basics
Quick intro
Python offers a robust suite of tools and frameworks for backend web development. Two popular frameworks are Flask and Django.
Flask is a lightweight, flexible framework for simple applications or when you need granular control. At the same time, Django is a high-level framework designed to make larger applications more accessible to build and maintain.
In this chapter, we’ll create a simple RESTful API using Flask, illustrating how to set up routes, handle requests, and return responses, following RESTful principles.
Note: You can run the following code examples by opening the built-in terminal within VS Code and executing the command: python <script>.py. Replace <script> with the name of the respective Python file to execute.
Flask: Creating a simple REST API
In this example, we’ll build a small API that manages a list of books. Each book will have an ID, title, and author.
We’ll cover how to set up Flask, create routes to handle various HTTP methods, and build a RESTful structure. Before starting, you’ll need to install Flask if it’s not already in your environment.
Code Listing 13-a: Command to Install Flask
pip install Flask |
Now, let’s explore the following Flask code.
Code Listing 13-b: flaskapi.py
from flask import Flask, jsonify, request # Initialize the Flask app app = Flask(__name__) # Sample data for the API books = [ {"id": 1, "title": "1984", "author": "George Orwell"}, {"id": 2, "title": "To Kill a Mockingbird", "author": "Harper Lee"}, ] # Define routes below |
Explanation:
· Importing libraries: Flask initializes the application, jsonify converts dictionaries to JSON format, and request retrieves data sent to the API.
· Initialize the app: app = Flask(__name__) creates the Flask app.
· Sample data: books is a list of dictionaries representing our data.
Defining RESTful API routes
We’ll create routes that correspond to typical RESTful operations: GET to retrieve data, POST to add data, PUT to update data, and DELETE to remove data.
Let’s expand the previous code (flaskapi.py) to include a route to get all books.
Code Listing 13-c: flaskapi.py
@app.route('/books', methods=['GET']) def get_books(): return jsonify(books), 200 |
Explanation:
· Route: @app.route('/books', methods=['GET']) binds this function to /books URL with the GET method.
· Function: get_books() returns all books in JSON format with a 200 HTTP status code, indicating a successful response.
Now, let’s create a route to get a single book ID.
Code Listing 13-d: flaskapi.py
@app.route('/books/<int:id>', methods=['GET']) def get_book(id): book = next((book for book in books if book["id"] == id), None) if book: return jsonify(book), 200 else: return jsonify({"error": "Book not found"}), 404 |
Explanation:
· Dynamic route: /<int:id> allows dynamic handling of book IDs.
· Logic: Uses next() to retrieve a book with the given ID; if not found, returns a 404 error message.
Next, let’s add a route to add a new book.
Code Listing 13-e: flaskapi.py
@app.route('/books', methods=['POST']) def add_book(): new_book = request.get_json() new_book["id"] = books[-1]["id"] + 1 if books else 1 # Auto-increment ID books.append(new_book) return jsonify(new_book), 201 |
Explanation:
· POST method: This route listens for POST requests at /books.
· Adding data: request.get_json() fetches the JSON payload; the ID is incremented, and the new book is appended to the books list.
· Response: Returns the new book data and a 201 status code, indicating a resource was successfully created.
Now, let’s add a route to update an existing book.
Code Listing 13-f: flaskapi.py
@app.route('/books/<int:id>', methods=['PUT']) def update_book(id): book = next((book for book in books if book["id"] == id), None) if book: data = request.get_json() book.update(data) return jsonify(book), 200 else: return jsonify({"error": "Book not found"}), 404 |
Explanation:
· PUT method: Listens for PUT requests at /books/<int:id>.
· Updating data: Finds the book by ID and updates it with data from request.get_json().
· Conditional response: If the book is not found, it returns a 404 error.
Now, let’s add a route to delete a book.
Code Listing 13-g: flaskapi.py
@app.route('/books/<int:id>', methods=['DELETE']) def delete_book(id): global books books = [book for book in books if book["id"] != id] return jsonify({"message": "Book deleted"}), 200 |
Explanation:
· DELETE method: Listens for DELETE requests at /books/<int:id>.
· Deleting data: Uses a list comprehension to filter out the book with the specified ID.
· Response: Returns a message confirming deletion.
Run the Flask app
To run the application, we must add this at the end of the flaskapi.py script.
Code Listing 13-h: flaskapi.py
if __name__ == '__main__': app.run(debug=True) |
Then, execute the app by invoking the python flaskapi.py command. The app will run on http://127.0.0.1:5000, where you can request your API routes.
This entire code snippet outlines how to use Flask to build a simple RESTful API, including routes for all CRUD operations, as previously discussed.
Code Listing 13-i: Finished - flaskapi.py
from flask import Flask, jsonify, request # Initialize the Flask app app = Flask(__name__) # Sample data for the API books = [ {"id": 1, "title": "1984", "author": "George Orwell"}, {"id": 2, "title": "To Kill a Mockingbird", "author": "Harper Lee"}, ] # Define routes below @app.route('/books', methods=['GET']) def get_books(): return jsonify(books), 200 @app.route('/books/<int:id>', methods=['GET']) def get_book(id): book = next((book for book in books if book["id"] == id), None) if book: return jsonify(book), 200 else: return jsonify({"error": "Book not found"}), 404 @app.route('/books', methods=['POST']) def add_book(): new_book = request.get_json() new_book["id"] = books[-1]["id"] + 1 if books else 1 # Auto-increment ID books.append(new_book) return jsonify(new_book), 201 @app.route('/books/<int:id>', methods=['PUT']) def update_book(id): book = next((book for book in books if book["id"] == id), None) if book: data = request.get_json() book.update(data) return jsonify(book), 200 else: return jsonify({"error": "Book not found"}), 404 @app.route('/books/<int:id>', methods=['DELETE']) def delete_book(id): global books books = [book for book in books if book["id"] != id] return jsonify({"message": "Book deleted"}), 200 if __name__ == '__main__': app.run(debug=True) |
RESTful API design principles
REST—which stands for representational state transfer—is an architectural style for designing networked applications, which has become the cornerstone of most web APIs used today. Key principles include:
· Stateless operations: Each request is independent and contains all necessary information.
· Uniform interface: API design follows consistent, predictable URL structures and response formats.
· HTTP methods: GET, POST, PUT, DELETE, and PATCH map directly to CRUD operations.
· Resource-based: URLs represent resources (e.g., /books/1 for a single book).
· Stateless communication: Each API call is independent, making it easier to scale.
Recap
In this chapter, we covered web development basics using Flask, a popular framework for Python. We created a RESTful API with CRUD capabilities and explored principles of REST API design, such as statelessness, resource-based URLs, and HTTP method conventions.
By following these principles, you can design and build scalable APIs that form the backbone of modern web and mobile applications.
With its simplicity and flexibility, Flask provides an excellent foundation for learning backend development in Python.
- 1800+ high-performance UI components.
- Includes popular controls such as Grid, Chart, Scheduler, and more.
- 24x5 unlimited support by developers.