|
@@ -1,21 +1,204 @@
|
|
|
import sqlite3
|
|
|
|
|
|
-from flask_sqlalchemy import SQLAlchemy
|
|
|
-from flask import Blueprint, request, jsonify, g, current_app
|
|
|
-from .model import predict
|
|
|
+from flask import Blueprint, request, jsonify, current_app
|
|
|
+from .model import predict, train_and_save_model
|
|
|
import pandas as pd
|
|
|
-
|
|
|
+from . import db # 从 app 包导入 db 实例
|
|
|
+from sqlalchemy.engine.reflection import Inspector
|
|
|
+from .database_models import Model, ModelParameters, Dataset
|
|
|
+import os
|
|
|
+from .utils import create_dynamic_table, allowed_file
|
|
|
+from sqlalchemy.orm import sessionmaker
|
|
|
|
|
|
# 创建蓝图 (Blueprint),用于分离路由
|
|
|
bp = Blueprint('routes', __name__)
|
|
|
-DATABASE = 'SoilAcidification.db'
|
|
|
|
|
|
+@bp.route('/upload-dataset', methods=['POST'])
|
|
|
+def upload_dataset():
|
|
|
+ try:
|
|
|
+ # 检查是否包含文件
|
|
|
+ if 'file' not in request.files:
|
|
|
+ return jsonify({'error': 'No file part'}), 400
|
|
|
+ file = request.files['file']
|
|
|
+
|
|
|
+ # 如果没有文件或者文件名为空
|
|
|
+ if file.filename == '':
|
|
|
+ return jsonify({'error': 'No selected file'}), 400
|
|
|
+
|
|
|
+ # 检查文件类型是否允许
|
|
|
+ if file and allowed_file(file.filename):
|
|
|
+ # 获取数据集的元数据
|
|
|
+ dataset_name = request.form.get('dataset_name')
|
|
|
+ dataset_description = request.form.get('dataset_description', 'No description provided')
|
|
|
+ dataset_type = request.form.get('dataset_type') # 新增字段:数据集类型
|
|
|
+
|
|
|
+ # 校验 dataset_type 是否存在
|
|
|
+ if not dataset_type:
|
|
|
+ return jsonify({'error': 'Dataset type is required'}), 400
|
|
|
+
|
|
|
+ # 创建 Dataset 实体并保存到数据库
|
|
|
+ new_dataset = Dataset(
|
|
|
+ DatasetName=dataset_name,
|
|
|
+ DatasetDescription=dataset_description,
|
|
|
+ RowCount=0, # 初步创建数据集时,行数先置为0
|
|
|
+ Status='pending', # 状态默认为 'pending'
|
|
|
+ DatasetType=dataset_type # 保存数据集类型
|
|
|
+ )
|
|
|
+ db.session.add(new_dataset)
|
|
|
+ db.session.commit()
|
|
|
+
|
|
|
+ # 获取数据集的 ID
|
|
|
+ dataset_id = new_dataset.DatasetID
|
|
|
+
|
|
|
+ # 保存文件时使用数据库的 DatasetID 作为文件名
|
|
|
+ unique_filename = f"dataset_{dataset_id}.xlsx"
|
|
|
+ upload_folder = current_app.config['UPLOAD_FOLDER']
|
|
|
+ file_path = os.path.join(upload_folder, unique_filename)
|
|
|
+
|
|
|
+ # 保存文件
|
|
|
+ file.save(file_path)
|
|
|
+
|
|
|
+ # 读取 Excel 文件内容
|
|
|
+ dataset_df = pd.read_excel(file_path)
|
|
|
+
|
|
|
+ # 更新数据集的行数
|
|
|
+ row_count = len(dataset_df)
|
|
|
+ new_dataset.RowCount = row_count
|
|
|
+ new_dataset.Status = 'processed' # 状态更新为 processed
|
|
|
+ db.session.commit()
|
|
|
+
|
|
|
+ # 动态创建数据表
|
|
|
+ columns = {}
|
|
|
+ for col in dataset_df.columns:
|
|
|
+ if dataset_df[col].dtype == 'int64':
|
|
|
+ columns[col] = 'int'
|
|
|
+ elif dataset_df[col].dtype == 'float64':
|
|
|
+ columns[col] = 'float'
|
|
|
+ else:
|
|
|
+ columns[col] = 'str'
|
|
|
+
|
|
|
+ # 创建新表格(动态表格)
|
|
|
+ dynamic_table_class = create_dynamic_table(dataset_id, columns)
|
|
|
+
|
|
|
+ # 创建新的数据库会话
|
|
|
+ Session = sessionmaker(bind=db.engine)
|
|
|
+ session = Session()
|
|
|
+
|
|
|
+ # 将每一行数据插入到动态创建的表格中
|
|
|
+ for _, row in dataset_df.iterrows():
|
|
|
+ record_data = row.to_dict()
|
|
|
+ # 将数据插入到新表格中
|
|
|
+ session.execute(dynamic_table_class.__table__.insert(), [record_data])
|
|
|
+
|
|
|
+ session.commit()
|
|
|
+ session.close()
|
|
|
+
|
|
|
+ return jsonify({
|
|
|
+ 'message': f'Dataset {dataset_name} uploaded successfully!',
|
|
|
+ 'dataset_id': new_dataset.DatasetID,
|
|
|
+ 'filename': unique_filename
|
|
|
+ }), 201
|
|
|
+
|
|
|
+ else:
|
|
|
+ return jsonify({'error': 'Invalid file type'}), 400
|
|
|
+
|
|
|
+ except Exception as e:
|
|
|
+ return jsonify({'error': str(e)}), 500
|
|
|
+
|
|
|
+
|
|
|
+@bp.route('/tables', methods=['GET'])
|
|
|
+def list_tables():
|
|
|
+ engine = db.engine # 使用 db 实例的 engine
|
|
|
+ inspector = Inspector.from_engine(engine) # 创建 Inspector 对象
|
|
|
+ table_names = inspector.get_table_names() # 获取所有表名
|
|
|
+ return jsonify(table_names) # 以 JSON 形式返回表名列表
|
|
|
+
|
|
|
+@bp.route('/models/<int:model_id>', methods=['GET'])
|
|
|
+def get_model(model_id):
|
|
|
+ try:
|
|
|
+ model = Model.query.filter_by(ModelID=model_id).first()
|
|
|
+ if model:
|
|
|
+ return jsonify({
|
|
|
+ 'ModelID': model.ModelID,
|
|
|
+ 'ModelName': model.ModelName,
|
|
|
+ 'ModelType': model.ModelType,
|
|
|
+ 'CreatedAt': model.CreatedAt.strftime('%Y-%m-%d %H:%M:%S'),
|
|
|
+ 'Description': model.Description
|
|
|
+ })
|
|
|
+ else:
|
|
|
+ return jsonify({'message': 'Model not found'}), 404
|
|
|
+ except Exception as e:
|
|
|
+ return jsonify({'error': 'Internal server error', 'message': str(e)}), 500
|
|
|
+
|
|
|
+@bp.route('/models', methods=['GET'])
|
|
|
+def get_all_models():
|
|
|
+ try:
|
|
|
+ models = Model.query.all() # 获取所有模型数据
|
|
|
+ if models:
|
|
|
+ result = [
|
|
|
+ {
|
|
|
+ 'ModelID': model.ModelID,
|
|
|
+ 'ModelName': model.ModelName,
|
|
|
+ 'ModelType': model.ModelType,
|
|
|
+ 'CreatedAt': model.CreatedAt.strftime('%Y-%m-%d %H:%M:%S'),
|
|
|
+ 'Description': model.Description
|
|
|
+ }
|
|
|
+ for model in models
|
|
|
+ ]
|
|
|
+ return jsonify(result)
|
|
|
+ else:
|
|
|
+ return jsonify({'message': 'No models found'}), 404
|
|
|
+ except Exception as e:
|
|
|
+ return jsonify({'error': 'Internal server error', 'message': str(e)}), 500
|
|
|
|
|
|
-def get_db():
|
|
|
- db = getattr(g, '_database', None)
|
|
|
- if db is None:
|
|
|
- db = g._database = sqlite3.connect(DATABASE)
|
|
|
- return db
|
|
|
+@bp.route('/model-parameters', methods=['GET'])
|
|
|
+def get_all_model_parameters():
|
|
|
+ try:
|
|
|
+ parameters = ModelParameters.query.all() # 获取所有参数数据
|
|
|
+ if parameters:
|
|
|
+ result = [
|
|
|
+ {
|
|
|
+ 'ParamID': param.ParamID,
|
|
|
+ 'ModelID': param.ModelID,
|
|
|
+ 'ParamName': param.ParamName,
|
|
|
+ 'ParamValue': param.ParamValue
|
|
|
+ }
|
|
|
+ for param in parameters
|
|
|
+ ]
|
|
|
+ return jsonify(result)
|
|
|
+ else:
|
|
|
+ return jsonify({'message': 'No parameters found'}), 404
|
|
|
+ except Exception as e:
|
|
|
+ return jsonify({'error': 'Internal server error', 'message': str(e)}), 500
|
|
|
+
|
|
|
+@bp.route('/models/<int:model_id>/parameters', methods=['GET'])
|
|
|
+def get_model_parameters(model_id):
|
|
|
+ try:
|
|
|
+ model = Model.query.filter_by(ModelID=model_id).first()
|
|
|
+ if model:
|
|
|
+ # 获取该模型的所有参数
|
|
|
+ parameters = [
|
|
|
+ {
|
|
|
+ 'ParamID': param.ParamID,
|
|
|
+ 'ParamName': param.ParamName,
|
|
|
+ 'ParamValue': param.ParamValue
|
|
|
+ }
|
|
|
+ for param in model.parameters
|
|
|
+ ]
|
|
|
+
|
|
|
+ # 返回模型参数信息
|
|
|
+ return jsonify({
|
|
|
+ 'ModelID': model.ModelID,
|
|
|
+ 'ModelName': model.ModelName,
|
|
|
+ 'ModelType': model.ModelType,
|
|
|
+ 'CreatedAt': model.CreatedAt.strftime('%Y-%m-%d %H:%M:%S'),
|
|
|
+ 'Description': model.Description,
|
|
|
+ 'Parameters': parameters
|
|
|
+ })
|
|
|
+ else:
|
|
|
+ return jsonify({'message': 'Model not found'}), 404
|
|
|
+ except Exception as e:
|
|
|
+ return jsonify({'error': 'Internal server error', 'message': str(e)}), 500
|
|
|
|
|
|
|
|
|
@bp.route('/predict', methods=['POST'])
|