|
1 |
| -[← Back to Main README](../README.md) |
2 |
| - |
3 |
| -# CRUD API |
4 |
| - |
5 |
| -Creating a CRUD (Create, Read, Update, Delete) API with MongoDB and Python for managing user data and online product information. We'll use Flask, a popular lightweight web framework, and PyMongo, the MongoDB driver for Python. Here's a step-by-step guide to get you started: |
6 |
| - |
7 |
| -## API with Native App Install |
8 |
| - |
9 |
| -> :warning: This approach **will only work if the application is runnning natively** in the host. To run this application in a container further steps are required and should visit: [Running your application with containers](DOCKER.md) |
10 |
| -
|
11 |
| -### Step 1: Setting Up the Environment |
12 |
| - |
13 |
| -1. **Install MongoDB**: Make sure MongoDB is installed and running on your system. You can download it from the official MongoDB website. (NOTE: It can also be a mongo server running container). |
14 |
| - |
15 |
| -2. **Create a Virtual Environment (Optional but Recommended)**: |
16 |
| - ```bash |
17 |
| - python3 -m venv .venv |
18 |
| - source venv/bin/activate # On Windows, use .venv\Scripts\activate |
19 |
| - ``` |
20 |
| - |
21 |
| -3. **Install Required Packages**: |
22 |
| - ```bash |
23 |
| - pip install Flask pymongo docker |
24 |
| - ``` |
25 |
| - |
26 |
| -4. If is not running already relaunch `mongodb-server` container |
27 |
| - |
28 |
| - ```bash |
29 |
| - docker run --rm --name mongodb-server -d -p 27017:27017 mongo |
30 |
| - ``` |
31 |
| - |
32 |
| -### Step 2: Initialize Flask App |
33 |
| - |
34 |
| -Create a new Python file (e.g., `app.py`) and set up a basic Flask app. |
35 |
| - |
36 |
| -```python |
37 |
| -from flask import Flask, jsonify, request |
38 |
| -from pymongo import MongoClient |
39 |
| -
|
40 |
| -app = Flask(__name__) |
41 |
| -# NOTE! This only work when run natively (on host) |
42 |
| -client = MongoClient("mongodb://localhost:27017/") |
43 |
| -db = client.test_db # database name |
44 |
| -
|
45 |
| -@app.route('/') |
46 |
| -def index(): |
47 |
| - return 'Connected to MongoDB version: ' + str(db.command("serverStatus")['version']) |
48 |
| -
|
49 |
| -if __name__ == '__main__': |
50 |
| - app.run(host='0.0.0.0', debug=True) |
51 |
| -``` |
52 |
| - |
53 |
| -### Step 3: Define the CRUD Operations |
54 |
| - |
55 |
| -1. **Create (POST)** - Add a new product or user. |
56 |
| -2. **Read (GET)** - Retrieve existing product or user details. |
57 |
| -3. **Update (PUT/PATCH)** - Modify an existing product or user. |
58 |
| -4. **Delete (DELETE)** - Remove a product or user from the database. |
59 |
| - |
60 |
| -Here's how you can define these operations: |
61 |
| -
|
62 |
| -#### Adding a Product/users |
63 |
| -
|
64 |
| -Add this to your existent code in `app.py` on your root directory: |
65 |
| -
|
66 |
| -```python |
67 |
| -# CREATE |
68 |
| -@app.route('/products', methods=['POST']) |
69 |
| -def add_product(): |
70 |
| - product_data = request.get_json() |
71 |
| - result = db.products.insert_one(product_data) |
72 |
| - return jsonify({"message": "Product created successfully", "id": str(result.inserted_id)}), 201 |
73 |
| -
|
74 |
| -
|
75 |
| -@app.route('/users', methods=['POST']) |
76 |
| -def add_user(): |
77 |
| - user_data = request.get_json() |
78 |
| - result = db.users.insert_one(user_data) |
79 |
| - return jsonify({"message": "User created successfully", "id": str(result.inserted_id)}), 201 |
80 |
| -
|
81 |
| -``` |
82 |
| -
|
83 |
| -#### Retrieving a Product/users |
84 |
| -
|
85 |
| -```python |
86 |
| -# READ |
87 |
| -@app.route('/products/<product_id>', methods=['GET']) |
88 |
| -def get_product(product_id): |
89 |
| - product = db.products.find_one({"product_id": product_id}) |
90 |
| - if product: |
91 |
| - product['_id'] = str(product['_id']) |
92 |
| - return jsonify(product) |
93 |
| - else: |
94 |
| - return jsonify({"message": "Product not found"}), 404 |
95 |
| -
|
96 |
| -
|
97 |
| -@app.route('/users/<username>', methods=['GET']) |
98 |
| -def get_user(username): |
99 |
| - user = db.users.find_one({"username": username}) |
100 |
| - if user: |
101 |
| - user['_id'] = str(user['_id']) # Convert ObjectId to string for JSON serialization |
102 |
| - return jsonify(user) |
103 |
| - else: |
104 |
| - return jsonify({"message": "User not found"}), 404 |
105 |
| -
|
106 |
| -``` |
107 |
| -
|
108 |
| -#### Updating a Product/users |
109 |
| -
|
110 |
| -```python |
111 |
| -# UPDATE |
112 |
| -@app.route('/products/<product_id>', methods=['PUT']) |
113 |
| -def update_product(product_id): |
114 |
| - update_data = request.get_json() |
115 |
| - result = db.products.update_one({"product_id": product_id}, {"$set": update_data}) |
116 |
| -
|
117 |
| - if result.matched_count: |
118 |
| - return jsonify({"message": "Product updated successfully"}), 200 |
119 |
| - else: |
120 |
| - return jsonify({"message": "Product not found"}), 404 |
121 |
| -
|
122 |
| -
|
123 |
| -@app.route('/users/<username>', methods=['PUT']) |
124 |
| -def update_user(username): |
125 |
| - update_data = request.get_json() |
126 |
| - result = db.users.update_one({"username": username}, {"$set": update_data}) |
127 |
| -
|
128 |
| - if result.matched_count: |
129 |
| - return jsonify({"message": "User updated successfully"}), 200 |
130 |
| - else: |
131 |
| - return jsonify({"message": "User not found"}), 404 |
132 |
| -``` |
133 |
| -
|
134 |
| -#### Deleting a Product/users |
135 |
| -
|
136 |
| -```python |
137 |
| -# DELETE |
138 |
| -@app.route('/products/<product_id>', methods=['DELETE']) |
139 |
| -def delete_product(product_id): |
140 |
| - result = db.products.delete_one({"product_id": product_id}) |
141 |
| -
|
142 |
| - if result.deleted_count: |
143 |
| - return jsonify({"message": "Product deleted successfully"}), 200 |
144 |
| - else: |
145 |
| - return jsonify({"message": "Product not found"}), 404 |
146 |
| -
|
147 |
| -
|
148 |
| -
|
149 |
| -@app.route('/users/<username>', methods=['DELETE']) |
150 |
| -def delete_user(username): |
151 |
| - result = db.users.delete_one({"username": username}) |
152 |
| -
|
153 |
| - if result.deleted_count: |
154 |
| - return jsonify({"message": "User deleted successfully"}), 200 |
155 |
| - else: |
156 |
| - return jsonify({"message": "User not found"}), 404 |
157 |
| -``` |
158 |
| -
|
159 |
| -### Step 4: Run the Flask App |
160 |
| -
|
161 |
| -Run the Flask app with the command: |
162 |
| -
|
163 |
| -```bash |
164 |
| -python app.py |
165 |
| -``` |
166 |
| -
|
167 |
| -### Step 5: Test the application |
168 |
| -
|
169 |
| -There are several ways of testing this, the most recommended one would be using a service like `Postman` |
170 |
| -
|
171 |
| -- **Postman** |
172 |
| -- **Curl** |
173 |
| -- **Web Browser** |
174 |
| -
|
175 |
| -> For more details on how to test, have a look into [TESTING.md](./TESTING.md) |
176 |
| -
|
177 |
| -
|
178 |
| -### Additional Considerations |
179 |
| -
|
180 |
| -- **Error Handling**: Add proper error handling to make your API robust. |
181 |
| -- **Authentication**: Implement authentication (like JWT) for secure access. |
182 |
| -- **Data Validation**: Validate incoming data for consistency and security. |
183 |
| -- **Unit Testing**: Write tests to ensure your API works as expected. |
184 |
| -
|
185 |
| -This guide should get you started. As you progress, you might want to refine the structure, add more features, or even containerize the app using Docker for easier deployment. Since you have experience in Docker, it can be a great addition to this project. Happy coding! |
186 |
| -
|
187 |
| ---- |
188 |
| -
|
| 1 | +[← Back to Main README](../README.md) |
| 2 | + |
| 3 | +# CRUD API |
| 4 | + |
| 5 | +Creating a CRUD (Create, Read, Update, Delete) API with MongoDB and Python for managing user data and online product information. We'll use Flask, a popular lightweight web framework, and PyMongo, the MongoDB driver for Python. Here's a step-by-step guide to get you started: |
| 6 | + |
| 7 | +## API with Native App Install |
| 8 | + |
| 9 | +> :warning: This approach **will only work if the application is runnning natively** in the host. To run this application in a container further steps are required and should visit: [Running your application with containers](DOCKER.md) |
| 10 | +
|
| 11 | +### Step 1: Setting Up the Environment |
| 12 | + |
| 13 | +1. **Install MongoDB**: Make sure MongoDB is installed and running on your system. You can download it from the official MongoDB website. (NOTE: It can also be a mongo server running container). |
| 14 | + |
| 15 | +2. **Create a Virtual Environment (Optional but Recommended)**: |
| 16 | + ```bash |
| 17 | + python3 -m venv .venv |
| 18 | + source venv/bin/activate # On Windows, use .venv\Scripts\activate |
| 19 | + ``` |
| 20 | + |
| 21 | +3. **Install Required Packages**: |
| 22 | + ```bash |
| 23 | + pip install Flask pymongo docker |
| 24 | + ``` |
| 25 | + |
| 26 | +4. If is not running already relaunch `mongodb-server` container |
| 27 | + |
| 28 | + ```bash |
| 29 | + docker run --rm --name mongodb-server -d -p 27017:27017 mongo |
| 30 | + ``` |
| 31 | + |
| 32 | +### Step 2: Initialize Flask App |
| 33 | + |
| 34 | +Create a new Python file (e.g., `app.py`) and set up a basic Flask app. |
| 35 | + |
| 36 | +```python |
| 37 | +from flask import Flask, jsonify, request |
| 38 | +from pymongo import MongoClient |
| 39 | +
|
| 40 | +app = Flask(__name__) |
| 41 | +# NOTE! This only work when run natively (on host) |
| 42 | +client = MongoClient("mongodb://localhost:27017/") |
| 43 | +db = client.test_db # database name |
| 44 | +
|
| 45 | +@app.route('/') |
| 46 | +def index(): |
| 47 | + return 'Connected to MongoDB version: ' + str(db.command("serverStatus")['version']) |
| 48 | +
|
| 49 | +if __name__ == '__main__': |
| 50 | + app.run(host='0.0.0.0', debug=True) |
| 51 | +``` |
| 52 | + |
| 53 | +### Step 3: Define the CRUD Operations |
| 54 | + |
| 55 | +1. **Create (POST)** - Add a new product or user. |
| 56 | +2. **Read (GET)** - Retrieve existing product or user details. |
| 57 | +3. **Update (PUT/PATCH)** - Modify an existing product or user. |
| 58 | +4. **Delete (DELETE)** - Remove a product or user from the database. |
| 59 | + |
| 60 | +Here's how you can define these operations: |
| 61 | +
|
| 62 | +#### Adding a Product/users |
| 63 | +
|
| 64 | +Add this to your existent code in `app.py` on your root directory: |
| 65 | +
|
| 66 | +```python |
| 67 | +# CREATE |
| 68 | +@app.route('/products', methods=['POST']) |
| 69 | +def add_product(): |
| 70 | + product_data = request.get_json() |
| 71 | + result = db.products.insert_one(product_data) |
| 72 | + return jsonify({"message": "Product created successfully", "id": str(result.inserted_id)}), 201 |
| 73 | +
|
| 74 | +
|
| 75 | +@app.route('/users', methods=['POST']) |
| 76 | +def add_user(): |
| 77 | + user_data = request.get_json() |
| 78 | + result = db.users.insert_one(user_data) |
| 79 | + return jsonify({"message": "User created successfully", "id": str(result.inserted_id)}), 201 |
| 80 | +
|
| 81 | +``` |
| 82 | +
|
| 83 | +#### Retrieving a Product/users |
| 84 | +
|
| 85 | +```python |
| 86 | +# READ |
| 87 | +@app.route('/products/<product_id>', methods=['GET']) |
| 88 | +def get_product(product_id): |
| 89 | + product = db.products.find_one({"product_id": product_id}) |
| 90 | + if product: |
| 91 | + product['_id'] = str(product['_id']) |
| 92 | + return jsonify(product) |
| 93 | + else: |
| 94 | + return jsonify({"message": "Product not found"}), 404 |
| 95 | +
|
| 96 | +
|
| 97 | +@app.route('/users/<username>', methods=['GET']) |
| 98 | +def get_user(username): |
| 99 | + user = db.users.find_one({"username": username}) |
| 100 | + if user: |
| 101 | + user['_id'] = str(user['_id']) # Convert ObjectId to string for JSON serialization |
| 102 | + return jsonify(user) |
| 103 | + else: |
| 104 | + return jsonify({"message": "User not found"}), 404 |
| 105 | +
|
| 106 | +``` |
| 107 | +
|
| 108 | +#### Updating a Product/users |
| 109 | +
|
| 110 | +```python |
| 111 | +# UPDATE |
| 112 | +@app.route('/products/<product_id>', methods=['PUT']) |
| 113 | +def update_product(product_id): |
| 114 | + update_data = request.get_json() |
| 115 | + result = db.products.update_one({"product_id": product_id}, {"$set": update_data}) |
| 116 | +
|
| 117 | + if result.matched_count: |
| 118 | + return jsonify({"message": "Product updated successfully"}), 200 |
| 119 | + else: |
| 120 | + return jsonify({"message": "Product not found"}), 404 |
| 121 | +
|
| 122 | +
|
| 123 | +@app.route('/users/<username>', methods=['PUT']) |
| 124 | +def update_user(username): |
| 125 | + update_data = request.get_json() |
| 126 | + result = db.users.update_one({"username": username}, {"$set": update_data}) |
| 127 | +
|
| 128 | + if result.matched_count: |
| 129 | + return jsonify({"message": "User updated successfully"}), 200 |
| 130 | + else: |
| 131 | + return jsonify({"message": "User not found"}), 404 |
| 132 | +``` |
| 133 | +
|
| 134 | +#### Deleting a Product/users |
| 135 | +
|
| 136 | +```python |
| 137 | +# DELETE |
| 138 | +@app.route('/products/<product_id>', methods=['DELETE']) |
| 139 | +def delete_product(product_id): |
| 140 | + result = db.products.delete_one({"product_id": product_id}) |
| 141 | +
|
| 142 | + if result.deleted_count: |
| 143 | + return jsonify({"message": "Product deleted successfully"}), 200 |
| 144 | + else: |
| 145 | + return jsonify({"message": "Product not found"}), 404 |
| 146 | +
|
| 147 | +
|
| 148 | +
|
| 149 | +@app.route('/users/<username>', methods=['DELETE']) |
| 150 | +def delete_user(username): |
| 151 | + result = db.users.delete_one({"username": username}) |
| 152 | +
|
| 153 | + if result.deleted_count: |
| 154 | + return jsonify({"message": "User deleted successfully"}), 200 |
| 155 | + else: |
| 156 | + return jsonify({"message": "User not found"}), 404 |
| 157 | +``` |
| 158 | +
|
| 159 | +### Step 4: Run the Flask App |
| 160 | +
|
| 161 | +Run the Flask app with the command: |
| 162 | +
|
| 163 | +```bash |
| 164 | +python app.py |
| 165 | +``` |
| 166 | +
|
| 167 | +### Step 5: Test the application |
| 168 | +
|
| 169 | +There are several ways of testing this, the most recommended one would be using `Postman` and the `JSON` file under `tests` directory. |
| 170 | +
|
| 171 | +- **Postman** |
| 172 | +- **Curl** |
| 173 | +- **Web Browser** |
| 174 | +
|
| 175 | +> For more details on how to test, have a look into [TESTING.md](./TESTING.md) |
| 176 | +
|
| 177 | +--- |
| 178 | +
|
189 | 179 | [← Previous: Setup MongoDB for development](./MONGO.md) | [Next: Running your application with containers →](./DOCKER.md)
|
0 commit comments