├── README.md └── library_organizer ├── app ├── __init__.py ├── __pycache__ │ ├── __init__.cpython-312.pyc │ ├── models.cpython-312.pyc │ └── routes.cpython-312.pyc ├── config.py ├── models.py ├── routes.py └── templates │ └── index.html ├── database └── library.db ├── instance └── library.db ├── requirements.txt └── run.py /README.md: -------------------------------------------------------------------------------- 1 | # APIs-Guide 2 | 3 | 4 | ```markdown 5 | # Library Organizer API 6 | 7 | The Library Organizer is a simple Flask-based REST API for managing a collection of books. This project demonstrates how to create an API with Flask, SQLAlchemy, and SQLite, and how to interact with it using tools like Postman. It also serves as a resource for beginners to understand the basics of RESTful APIs. 8 | 9 | # Features 10 | 11 | - Add new books to the database. 12 | - Retrieve all books in the database. 13 | - Basic routing with Flask. 14 | - Database handling with SQLAlchemy. 15 | - Learn how APIs work through a real-world example. 16 | 17 | --- 18 | 19 | # What is an API? 20 | 21 | An API (Application Programming Interface) is a set of rules that allows applications to communicate with each other. For example, when you use a weather app to check the forecast, the app uses an API to fetch the data from a server. APIs enable data exchange between different systems, allowing them to interact in a structured and secure way. 22 | 23 | # Example: A Simple API Request 24 | Let's say you want to check the weather for your location. You might send a request to an API that looks like this: 25 | 26 | ``` 27 | 28 | ``` 29 | 30 | This request would return data like this: 31 | 32 | ```json 33 | { 34 | "location": "London", 35 | "temperature": "18°C", 36 | "condition": "Cloudy" 37 | } 38 | ``` 39 | 40 | This is a simplified example, but the idea is that the client (in this case, the weather app) makes a request to the server (the weather API) to get information. 41 | 42 | --- 43 | 44 | ## Notes on APIs 45 | 46 | ### What is REST? 47 | REST (Representational State Transfer) is an architectural style used for designing networked applications. It relies on a stateless, client-server communication model, where the server provides resources and the client can interact with these resources using standard HTTP methods. 48 | 49 | # Common HTTP Methods in REST APIs: 50 | 1. GET: Retrieves data from the server (e.g., retrieving a list of books). 51 | 2. POST: Sends data to the server (e.g., creating a new book entry). 52 | 3. PUT: Updates an existing resource on the server (e.g., modifying a book’s details). 53 | 4. DELETE: Deletes a resource from the server (e.g., removing a book). 54 | 55 | # HTTP Status Codes 56 | - 200 OK: The request was successful. 57 | - 201 Created: A resource was successfully created (e.g., a new book). 58 | - 400 Bad Request: The request was malformed or missing necessary data. 59 | - 404 Not Found: The requested resource does not exist. 60 | - 500 Internal Server Error: The server encountered an unexpected error. 61 | 62 | # JSON (JavaScript Object Notation) 63 | JSON is a lightweight data interchange format used in APIs. It's easy for humans to read and write, and easy for machines to parse and generate. In this project, the API uses JSON format to send and receive data about books. 64 | 65 | # Example JSON format for a book: 66 | ```json 67 | { 68 | "name": "Kafka on the Shore", 69 | "description": "Kafka on the Shore, a tour de force of metaphysical reality, is powered by two remarkable characters: a teenage boy, Kafka Tamura, who runs away from home either to escape a gruesome oedipal prophecy or to search for his long-missing mother and sister; and an aging simpleton called Nakata, who never recovered from a wartime affliction and now is drawn toward Kafka for reasons that, like the most basic activities of daily life", 70 | "pages": 600, 71 | "author": "Haruki Murakami" 72 | } 73 | ``` 74 | 75 | --- 76 | 77 | # Resources for learning APIs 78 | 79 | - REST API Crash Course (Video)](https://www.youtube.com/watch?v=qbLc5a9jdXo). 80 | - 7 Tips for API Design (Video)](https://www.youtube.com/watch?v=_gQaygjm_hg). 81 | - My Medium article (https://medium.com/@reemhassan742r/the-power-of-apis-a-guide-for-beginners-with-real-world-examples-120790ee07c8). 82 | - [RESTful API Design Guide](https://www.restapitutorial.com/). 83 | - [JSON Format Documentation](https://www.json.org/json-en.html). 84 | 85 | --- 86 | 87 | # Project Setup 88 | 89 | 1. Clone the repository: 90 | ```bash 91 | git clone https://github.com/your_username/library_organizer.git 92 | cd library_organizer 93 | ``` 94 | 95 | 2. Set up a virtual environment: 96 | ```bash 97 | python -m venv .venv 98 | source .venv/bin/activate # For Linux/Mac 99 | .venv\Scripts\activate # For Windows 100 | ``` 101 | 102 | 3. Install dependencies: 103 | ```bash 104 | pip install -r requirements.txt 105 | ``` 106 | 107 | 4. Initialize the database: 108 | ```bash 109 | python run.py 110 | ``` 111 | 112 | --- 113 | 114 | # API Endpoints 115 | 116 | 1. Get all books 117 | - URL: `/books` 118 | - Method: `GET` 119 | - Response: 120 | ```json 121 | [ 122 | { 123 | "id": 1, 124 | "name": "Book Title", 125 | "description": "A brief description of the book.", 126 | "pages": 300, 127 | "author": "Author Name" 128 | } 129 | ] 130 | ``` 131 | 132 | ### 2. Add a new book 133 | - URL: `/books` 134 | - Method: `POST` 135 | - Request body: 136 | ```json 137 | { 138 | "name": "Book Title", 139 | "description": "A brief description of the book.", 140 | "pages": 300, 141 | "author": "Author Name" 142 | } 143 | ``` 144 | - Response: 145 | ```json 146 | { 147 | "message": "Book added successfully!" 148 | } 149 | ``` 150 | 151 | --- 152 | 153 | # Testing with Postman 154 | 155 | 1. Install Postman: 156 | Download and install [Postman](https://www.postman.com/). 157 | 158 | 2. Start the Flask server: 159 | ```bash 160 | python run.py 161 | ``` 162 | 163 | 3. Set up requests in Postman: 164 | - Create a new `GET` request for `http://127.0.0.1:5000/books` to fetch all books. 165 | - Create a new `POST` request for `http://127.0.0.1:5000/books` to add a book. Include the JSON payload in the body. 166 | 167 | --- 168 | 169 | # Improvements Made During Development 170 | 171 | 1. Migrated from using Blueprints to a single-file `routes.py` for simplicity. 172 | 2. Removed JWT for better beginner accessibility. 173 | 3. Fixed database connection issues and ensured proper table creation. 174 | 4. Enhanced error handling for common API issues. 175 | 5. Improved documentation and project structure. 176 | 177 | --- 178 | 179 | # Learn More 180 | 181 | Explore the concepts behind this project and get more resources: 182 | - Flask Documentation: [Flask](https://flask.palletsprojects.com/) 183 | - SQLAlchemy Documentation: [SQLAlchemy](https://docs.sqlalchemy.org/) 184 | - Postman API Tool: [Postman](https://www.postman.com/) 185 | 186 | --- 187 | 188 | # Contributing 189 | 190 | Contributions are welcome! Feel free to fork this repository, make your changes, and submit a pull request. 191 | 192 | --- 193 | ``` 194 | -------------------------------------------------------------------------------- /library_organizer/app/__init__.py: -------------------------------------------------------------------------------- 1 | from flask import Flask 2 | from flask_sqlalchemy import SQLAlchemy 3 | from .models import db 4 | from .routes import register_routes 5 | 6 | def create_app(): 7 | app = Flask(__name__) 8 | 9 | # Configure the app for SQLAlchemy 10 | app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///library.db' 11 | app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False 12 | 13 | # Initialize SQLAlchemy with the app 14 | db.init_app(app) 15 | 16 | # Register routes 17 | register_routes(app) 18 | 19 | with app.app_context(): 20 | db.create_all() # Ensure tables are created 21 | 22 | return app 23 | -------------------------------------------------------------------------------- /library_organizer/app/__pycache__/__init__.cpython-312.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReemHassan742/APIs-Guide/349d4986ee2b657f1eb84fdf1d948e7ff4432aac/library_organizer/app/__pycache__/__init__.cpython-312.pyc -------------------------------------------------------------------------------- /library_organizer/app/__pycache__/models.cpython-312.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReemHassan742/APIs-Guide/349d4986ee2b657f1eb84fdf1d948e7ff4432aac/library_organizer/app/__pycache__/models.cpython-312.pyc -------------------------------------------------------------------------------- /library_organizer/app/__pycache__/routes.cpython-312.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReemHassan742/APIs-Guide/349d4986ee2b657f1eb84fdf1d948e7ff4432aac/library_organizer/app/__pycache__/routes.cpython-312.pyc -------------------------------------------------------------------------------- /library_organizer/app/config.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReemHassan742/APIs-Guide/349d4986ee2b657f1eb84fdf1d948e7ff4432aac/library_organizer/app/config.py -------------------------------------------------------------------------------- /library_organizer/app/models.py: -------------------------------------------------------------------------------- 1 | from flask_sqlalchemy import SQLAlchemy 2 | 3 | db = SQLAlchemy() 4 | 5 | class Book(db.Model): 6 | id = db.Column(db.Integer, primary_key=True) 7 | name = db.Column(db.String(100), nullable=False) 8 | description = db.Column(db.String(255), nullable=False) 9 | pages = db.Column(db.Integer, nullable=False) 10 | author = db.Column(db.String(100), nullable=False) 11 | 12 | -------------------------------------------------------------------------------- /library_organizer/app/routes.py: -------------------------------------------------------------------------------- 1 | from flask import Flask, jsonify, request 2 | from .models import db, Book 3 | 4 | def register_routes(app): 5 | @app.route("/") 6 | def home(): 7 | return jsonify({"message": "Welcome to the Library Organizer API!"}), 200 8 | 9 | # Get all books 10 | @app.route("/books", methods=["GET"]) 11 | def get_books(): 12 | books = Book.query.all() 13 | book_list = [ 14 | { 15 | "id": book.id, 16 | "name": book.name, 17 | "description": book.description, 18 | "pages": book.pages, 19 | "author": book.author 20 | } 21 | for book in books 22 | ] 23 | return jsonify({"books": book_list}), 200 24 | 25 | # Get a single book by ID 26 | @app.route("/books/", methods=["GET"]) 27 | def get_book(book_id): 28 | book = Book.query.get(book_id) 29 | if not book: 30 | return jsonify({"error": "Book not found"}), 404 31 | return jsonify( 32 | { 33 | "id": book.id, 34 | "name": book.name, 35 | "description": book.description, 36 | "pages": book.pages, 37 | "author": book.author 38 | } 39 | ), 200 40 | 41 | # Add a new book 42 | @app.route("/books", methods=["POST"]) 43 | def add_book(): 44 | data = request.get_json() 45 | if not data: 46 | return jsonify({"error": "No input data provided"}), 400 47 | 48 | name = data.get("name") 49 | description = data.get("description") 50 | pages = data.get("pages") 51 | author = data.get("author") 52 | 53 | if not all([name, description, pages, author]): 54 | return jsonify({"error": "All fields are required"}), 400 55 | 56 | new_book = Book(name=name, description=description, pages=pages, author=author) 57 | db.session.add(new_book) 58 | db.session.commit() 59 | 60 | return jsonify({"message": "Book added successfully!", "book": { 61 | "id": new_book.id, 62 | "name": new_book.name, 63 | "description": new_book.description, 64 | "pages": new_book.pages, 65 | "author": new_book.author 66 | }}), 201 67 | 68 | # Update an existing book 69 | @app.route("/books/", methods=["PUT"]) 70 | def update_book(book_id): 71 | book = Book.query.get(book_id) 72 | if not book: 73 | return jsonify({"error": "Book not found"}), 404 74 | 75 | data = request.get_json() 76 | book.name = data.get("name", book.name) 77 | book.description = data.get("description", book.description) 78 | book.pages = data.get("pages", book.pages) 79 | book.author = data.get("author", book.author) 80 | 81 | db.session.commit() 82 | return jsonify({"message": "Book updated successfully!"}), 200 83 | 84 | # Delete a book 85 | @app.route("/books/", methods=["DELETE"]) 86 | def delete_book(book_id): 87 | book = Book.query.get(book_id) 88 | if not book: 89 | return jsonify({"error": "Book not found"}), 404 90 | 91 | db.session.delete(book) 92 | db.session.commit() 93 | return jsonify({"message": "Book deleted successfully!"}), 200 94 | -------------------------------------------------------------------------------- /library_organizer/app/templates/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Library Organizer 7 | 8 | 9 |

Welcome to the Library Organizer

10 |

Use the API to register users, login, and manage books.

11 | 12 | 13 | -------------------------------------------------------------------------------- /library_organizer/database/library.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReemHassan742/APIs-Guide/349d4986ee2b657f1eb84fdf1d948e7ff4432aac/library_organizer/database/library.db -------------------------------------------------------------------------------- /library_organizer/instance/library.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReemHassan742/APIs-Guide/349d4986ee2b657f1eb84fdf1d948e7ff4432aac/library_organizer/instance/library.db -------------------------------------------------------------------------------- /library_organizer/requirements.txt: -------------------------------------------------------------------------------- 1 | Flask==2.3.3 2 | Flask-SQLAlchemy==3.0.5 3 | Werkzeug==2.3.7 4 | -------------------------------------------------------------------------------- /library_organizer/run.py: -------------------------------------------------------------------------------- 1 | from app import create_app 2 | 3 | app = create_app() 4 | 5 | if __name__ == "__main__": 6 | app.run(debug=True) 7 | --------------------------------------------------------------------------------