Building Project Files
هذا الالتزام موجود في:
163
fruit_api.py
Normal file
163
fruit_api.py
Normal file
@@ -0,0 +1,163 @@
|
||||
# fruit_api.py
|
||||
from flask import Flask, jsonify, request
|
||||
from datetime import datetime
|
||||
|
||||
app = Flask(__name__)
|
||||
|
||||
# In-memory database
|
||||
fruits = [
|
||||
{"id": 1, "name": "Apple", "color": "Red", "price": 1.50, "quantity": 100, "category": "Tropical"},
|
||||
{"id": 2, "name": "Banana", "color": "Yellow", "price": 0.75, "quantity": 150, "category": "Tropical"},
|
||||
{"id": 3, "name": "Orange", "color": "Orange", "price": 1.20, "quantity": 80, "category": "Citrus"}
|
||||
]
|
||||
|
||||
# 1. GET / - Home endpoint
|
||||
@app.route('/')
|
||||
def home():
|
||||
return jsonify({
|
||||
"message": "Fruit Store API",
|
||||
"version": "1.0",
|
||||
"endpoints": [
|
||||
"GET /fruits - Get all fruits",
|
||||
"GET /fruits/<id> - Get fruit by ID",
|
||||
"POST /fruits - Add new fruit",
|
||||
"PUT /fruits/<id> - Update fruit",
|
||||
"DELETE /fruits/<id> - Delete fruit",
|
||||
"GET /fruits/category/<category> - Get fruits by category",
|
||||
"GET /fruits/search?name=<name> - Search fruits by name"
|
||||
]
|
||||
})
|
||||
|
||||
# 2. GET /fruits - Get all fruits
|
||||
@app.route('/fruits', methods=['GET'])
|
||||
def get_all_fruits():
|
||||
return jsonify({
|
||||
"fruits": fruits,
|
||||
"total": len(fruits),
|
||||
"timestamp": datetime.now().isoformat()
|
||||
})
|
||||
|
||||
# 3. GET /fruits/<id> - Get specific fruit
|
||||
@app.route('/fruits/<int:fruit_id>', methods=['GET'])
|
||||
def get_fruit(fruit_id):
|
||||
fruit = next((f for f in fruits if f['id'] == fruit_id), None)
|
||||
if fruit:
|
||||
return jsonify({"fruit": fruit})
|
||||
return jsonify({"error": "Fruit not found"}), 404
|
||||
|
||||
# 4. POST /fruits - Create new fruit
|
||||
@app.route('/fruits', methods=['POST'])
|
||||
def create_fruit():
|
||||
data = request.get_json()
|
||||
|
||||
if not data or 'name' not in data:
|
||||
return jsonify({"error": "Name is required"}), 400
|
||||
|
||||
# Generate new ID
|
||||
new_id = max([f['id'] for f in fruits]) + 1 if fruits else 1
|
||||
|
||||
new_fruit = {
|
||||
"id": new_id,
|
||||
"name": data['name'],
|
||||
"color": data.get('color', 'Unknown'),
|
||||
"price": data.get('price', 0.0),
|
||||
"quantity": data.get('quantity', 0),
|
||||
"category": data.get('category', 'General'),
|
||||
"created_at": datetime.now().isoformat()
|
||||
}
|
||||
|
||||
fruits.append(new_fruit)
|
||||
return jsonify({
|
||||
"message": "Fruit created successfully",
|
||||
"fruit": new_fruit
|
||||
}), 201
|
||||
|
||||
# 5. PUT /fruits/<id> - Update fruit
|
||||
@app.route('/fruits/<int:fruit_id>', methods=['PUT'])
|
||||
def update_fruit(fruit_id):
|
||||
fruit = next((f for f in fruits if f['id'] == fruit_id), None)
|
||||
if not fruit:
|
||||
return jsonify({"error": "Fruit not found"}), 404
|
||||
|
||||
data = request.get_json()
|
||||
|
||||
# Update allowed fields
|
||||
if 'name' in data:
|
||||
fruit['name'] = data['name']
|
||||
if 'color' in data:
|
||||
fruit['color'] = data['color']
|
||||
if 'price' in data:
|
||||
fruit['price'] = data['price']
|
||||
if 'quantity' in data:
|
||||
fruit['quantity'] = data['quantity']
|
||||
if 'category' in data:
|
||||
fruit['category'] = data['category']
|
||||
|
||||
fruit['updated_at'] = datetime.now().isoformat()
|
||||
|
||||
return jsonify({
|
||||
"message": "Fruit updated successfully",
|
||||
"fruit": fruit
|
||||
})
|
||||
|
||||
# 6. DELETE /fruits/<id> - Delete fruit
|
||||
@app.route('/fruits/<int:fruit_id>', methods=['DELETE'])
|
||||
def delete_fruit(fruit_id):
|
||||
global fruits
|
||||
fruit = next((f for f in fruits if f['id'] == fruit_id), None)
|
||||
if not fruit:
|
||||
return jsonify({"error": "Fruit not found"}), 404
|
||||
|
||||
fruits = [f for f in fruits if f['id'] != fruit_id]
|
||||
return jsonify({
|
||||
"message": "Fruit deleted successfully",
|
||||
"deleted_fruit": fruit
|
||||
})
|
||||
|
||||
# 7. GET /fruits/category/<category> - Get fruits by category
|
||||
@app.route('/fruits/category/<category>', methods=['GET'])
|
||||
def get_fruits_by_category(category):
|
||||
category_fruits = [f for f in fruits if f['category'].lower() == category.lower()]
|
||||
return jsonify({
|
||||
"category": category,
|
||||
"fruits": category_fruits,
|
||||
"count": len(category_fruits)
|
||||
})
|
||||
|
||||
# Search endpoint
|
||||
@app.route('/fruits/search', methods=['GET'])
|
||||
def search_fruits():
|
||||
name_query = request.args.get('name', '').lower()
|
||||
if not name_query:
|
||||
return jsonify({"error": "Name parameter is required"}), 400
|
||||
|
||||
matching_fruits = [f for f in fruits if name_query in f['name'].lower()]
|
||||
return jsonify({
|
||||
"search_term": name_query,
|
||||
"results": matching_fruits,
|
||||
"count": len(matching_fruits)
|
||||
})
|
||||
|
||||
# Health check endpoint
|
||||
@app.route('/health', methods=['GET'])
|
||||
def health_check():
|
||||
return jsonify({
|
||||
"status": "healthy",
|
||||
"service": "fruit-api",
|
||||
"timestamp": datetime.now().isoformat()
|
||||
})
|
||||
|
||||
if __name__ == '__main__':
|
||||
print("Fruit API starting on http://localhost:5000")
|
||||
print("Available endpoints:")
|
||||
print("1. GET / - Home")
|
||||
print("2. GET /fruits - All fruits")
|
||||
print("3. GET /fruits/<id> - Fruit by ID")
|
||||
print("4. POST /fruits - Create fruit")
|
||||
print("5. PUT /fruits/<id> - Update fruit")
|
||||
print("6. DELETE /fruits/<id> - Delete fruit")
|
||||
print("7. GET /fruits/category/<category> - Fruits by category")
|
||||
print("8. GET /fruits/search?name=X - Search fruits")
|
||||
print("9. GET /health - Health check")
|
||||
|
||||
app.run(debug=True, host='0.0.0.0', port=5000)
|
المرجع في مشكلة جديدة
حظر مستخدم