You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
test/后端/flask+mysql flower/花卉上传和搜索功能实现.py

288 lines
9.5 KiB

from flask import Flask, request, jsonify
from flask_sqlalchemy import SQLAlchemy
from flask_cors import CORS
import requests
from datetime import datetime
import base64
app = Flask(__name__)
CORS(app)
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+pymysql://root@localhost/flower'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
UPLOAD_SERVICE_URL = 'https://c.2nicep.com:3000/uploads'
db = SQLAlchemy(app)
class FlowerShop(db.Model):
__tablename__ = 'flower_shop'
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
name = db.Column(db.String(100), nullable=False)
description = db.Column(db.Text, nullable=True)
price = db.Column(db.DECIMAL(10, 2), nullable=False)
quantity = db.Column(db.Integer, nullable=False, default=0)
image_url = db.Column(db.String(255), nullable=True)
is_active = db.Column(db.Boolean, default=True)
class Order(db.Model):
__tablename__ = 'orders'
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
flower_id = db.Column(db.Integer, db.ForeignKey('flower_shop.id'), nullable=False)
quantity = db.Column(db.Integer, nullable=False)
total_price = db.Column(db.DECIMAL(10, 2), nullable=False)
status = db.Column(db.String(20), nullable=False, default='pending')
created_at = db.Column(db.DateTime, nullable=False, default=datetime.utcnow)
flower = db.relationship('FlowerShop', backref=db.backref('orders', lazy=True))
API_KEY = "kbt40nMOF8tLGg5IdZStJc4G"
SECRET_KEY = "jUoj82HAALIzDWRlrTauoHwLcnB3eAn7"
def get_access_token():
url = "https://aip.baidubce.com/oauth/2.0/token"
params = {"grant_type": "client_credentials", "client_id": API_KEY, "client_secret": SECRET_KEY}
return str(requests.post(url, params=params).json().get("access_token"))
@app.route('/api/identify', methods=['POST'])
def identify_flower():
if 'image' not in request.files:
return jsonify({"error": "没有提供图片文件"}), 400
image_file = request.files['image']
image = base64.b64encode(image_file.read()).decode('utf-8')
url = "https://aip.baidubce.com/rest/2.0/image-classify/v1/plant?access_token=" + get_access_token()
payload = {
"image": image,
"baike_num": 0
}
headers = {
'Content-Type': 'application/x-www-form-urlencoded',
'Accept': 'application/json'
}
response = requests.post(url, headers=headers, data=payload)
result = response.json()
if 'result' in result and len(result['result']) > 0:
top_result = result['result'][0]
# 检查数据库中是否存在这种花
flower = FlowerShop.query.filter(FlowerShop.name.ilike(f"%{top_result['name']}%")).first()
if flower:
return jsonify({
"id": flower.id,
"name": flower.name,
"description": flower.description,
"price": float(flower.price),
"quantity": flower.quantity,
"image_url": flower.image_url
}), 200
else:
# 如果数据库中没有这种花,返回识别的名称和概率
return jsonify({
"name": top_result['name'],
"probability": top_result['score']
}), 200
else:
return jsonify({"error": "未能识别花卉"}), 404
def upload_file_to_service(file):
if not file:
return None
files = {'images': (file.filename, file.read(), file.content_type)}
try:
response = requests.post(UPLOAD_SERVICE_URL, files=files)
if response.status_code == 200:
return response.json()['files'][0]
else:
print(f"Upload failed: {response.text}")
return None
except Exception as e:
print(f"Error during upload: {str(e)}")
return None
@app.route('/api/flowers', methods=['GET'])
def get_flowers():
query = request.args.get('query', '')
flowers = FlowerShop.query.filter(FlowerShop.name.ilike(f'%{query}%'), FlowerShop.is_active == True).all()
return jsonify([{
"id": flower.id,
"name": flower.name,
"description": flower.description,
"price": float(flower.price),
"quantity": flower.quantity,
"image_url": flower.image_url
} for flower in flowers])
@app.route('/api/flowers', methods=['POST'])
def add_flower():
name = request.form.get('name')
description = request.form.get('description')
price = request.form.get('price')
quantity = request.form.get('quantity')
image = request.files.get('image')
if not name or not price or not quantity:
return jsonify({"error": "Name, price, and quantity are required"}), 400
try:
price = float(price)
quantity = int(quantity)
except ValueError:
return jsonify({"error": "Invalid price or quantity format"}), 400
if quantity < 0:
return jsonify({"error": "Quantity must be non-negative"}), 400
image_url = upload_file_to_service(image)
try:
new_flower = FlowerShop(name=name, description=description, price=price, quantity=quantity, image_url=image_url)
db.session.add(new_flower)
db.session.commit()
except Exception as e:
db.session.rollback()
print(f"Database error: {str(e)}")
return jsonify({"error": "Failed to add flower to database"}), 500
return jsonify({
"message": "Flower added successfully",
"id": new_flower.id,
"name": new_flower.name,
"description": new_flower.description,
"price": float(new_flower.price),
"quantity": new_flower.quantity,
"image_url": new_flower.image_url
}), 201
@app.route('/api/my-products', methods=['GET'])
def get_my_products():
products = FlowerShop.query.all()
return jsonify([{
"id": product.id,
"name": product.name,
"description": product.description,
"price": float(product.price),
"quantity": product.quantity,
"image_url": product.image_url,
"is_active": product.is_active
} for product in products])
@app.route('/api/products/<int:product_id>', methods=['PUT'])
def update_product(product_id):
product = FlowerShop.query.get_or_404(product_id)
data = request.json
product.name = data.get('name', product.name)
product.description = data.get('description', product.description)
product.price = data.get('price', product.price)
product.quantity = data.get('quantity', product.quantity)
product.is_active = data.get('is_active', product.is_active)
try:
db.session.commit()
except Exception as e:
db.session.rollback()
return jsonify({"error": f"Failed to update product: {str(e)}"}), 500
return jsonify({"message": "Product updated successfully"})
@app.route('/api/products/<int:product_id>/toggle-status', methods=['POST'])
def toggle_product_status(product_id):
product = FlowerShop.query.get_or_404(product_id)
product.is_active = not product.is_active
try:
db.session.commit()
except Exception as e:
db.session.rollback()
return jsonify({"error": f"Failed to toggle product status: {str(e)}"}), 500
return jsonify({"message": f"Product {'activated' if product.is_active else 'deactivated'} successfully"})
@app.route('/api/orders', methods=['GET'])
def get_orders():
try:
orders = Order.query.all()
return jsonify([{
"id": order.id,
"flowerName": order.flower.name if order.flower else "Unknown",
"quantity": order.quantity,
"totalPrice": float(order.total_price),
"status": order.status,
"createdAt": order.created_at.isoformat()
} for order in orders])
except Exception as e:
print(f"Error fetching orders: {str(e)}")
return jsonify({"error": "Failed to fetch orders"}), 500
@app.route('/api/orders', methods=['POST'])
def create_order():
data = request.json
flower_id = data.get('flowerId')
quantity = data.get('quantity', 1)
if not flower_id or not quantity:
return jsonify({"error": "Flower ID and quantity are required"}), 400
flower = FlowerShop.query.get(flower_id)
if not flower:
return jsonify({"error": "Flower not found"}), 404
if flower.quantity < quantity:
return jsonify({"error": "Not enough stock"}), 400
total_price = flower.price * quantity
try:
new_order = Order(flower_id=flower_id, quantity=quantity, total_price=total_price)
flower.quantity -= quantity # 减少库存
db.session.add(new_order)
db.session.commit()
except Exception as e:
db.session.rollback()
print(f"Database error: {str(e)}")
return jsonify({"error": "Failed to create order"}), 500
return jsonify({
"message": "Order created successfully",
"orderId": new_order.id,
"totalPrice": float(new_order.total_price)
}), 201
@app.route('/api/orders/<int:order_id>/cancel', methods=['POST'])
def cancel_order(order_id):
order = Order.query.get_or_404(order_id)
if order.status != 'pending':
return jsonify({"error": "Only pending orders can be cancelled"}), 400
try:
order.status = 'cancelled'
order.flower.quantity += order.quantity # 恢复库存
db.session.commit()
except Exception as e:
db.session.rollback()
return jsonify({"error": f"Failed to cancel order: {str(e)}"}), 500
return jsonify({"message": "Order cancelled successfully"})
if __name__ == '__main__':
with app.app_context():
db.create_all()
app.run(debug=True)