This commit is contained in:
pika 2025-03-30 23:42:24 +02:00
parent 3b2f1db4ce
commit 5c16964b76
47 changed files with 2080 additions and 1053 deletions

View file

@ -5,100 +5,101 @@ import csv
import io
import datetime
bp = Blueprint('importexport', __name__, url_prefix='/import-export')
bp = Blueprint("importexport", __name__, url_prefix="/import-export")
MODEL_MAP = {
'subnet': Subnet,
'server': Server,
'app': App
}
MODEL_MAP = {"subnet": Subnet, "server": Server, "app": App}
@bp.route('/export/<model_name>', methods=['GET'])
@bp.route("/export/<model_name>", methods=["GET"])
def export_model(model_name):
if model_name not in MODEL_MAP:
return jsonify({'error': 'Invalid model name'}), 400
return jsonify({"error": "Invalid model name"}), 400
model = MODEL_MAP[model_name]
instances = model.query.all()
# Create a CSV file in memory
output = io.StringIO()
writer = csv.writer(output)
# Get column names from model
columns = [column.name for column in model.__table__.columns]
writer.writerow(columns)
# Write data
for instance in instances:
row = [getattr(instance, column) for column in columns]
writer.writerow(row)
# Create response
timestamp = datetime.datetime.now().strftime('%Y%m%d_%H%M%S')
timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
filename = f"{model_name}_{timestamp}.csv"
response = make_response(output.getvalue())
response.headers['Content-Disposition'] = f'attachment; filename={filename}'
response.headers['Content-type'] = 'text/csv'
response.headers["Content-Disposition"] = f"attachment; filename={filename}"
response.headers["Content-type"] = "text/csv"
return response
@bp.route('/import/<model_name>', methods=['GET', 'POST'])
@bp.route("/import/<model_name>", methods=["GET", "POST"])
def import_model(model_name):
if model_name not in MODEL_MAP:
return jsonify({'error': 'Invalid model name'}), 400
return jsonify({"error": "Invalid model name"}), 400
model = MODEL_MAP[model_name]
if request.method == 'GET':
if request.method == "GET":
# Show import form
return render_template('import_form.html', model_name=model_name)
return render_template("import_form.html", model_name=model_name)
# Process CSV upload
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 not file.filename.endswith('.csv'):
return jsonify({'error': 'File must be CSV format'}), 400
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 not file.filename.endswith(".csv"):
return jsonify({"error": "File must be CSV format"}), 400
try:
# Read CSV
stream = io.StringIO(file.stream.read().decode("UTF8"), newline=None)
csv_reader = csv.reader(stream)
# Get headers
headers = next(csv_reader)
# Validate required columns
required_columns = [col.name for col in model.__table__.columns
if not col.nullable and col.name != 'id']
required_columns = [
col.name
for col in model.__table__.columns
if not col.nullable and col.name != "id"
]
for col in required_columns:
if col not in headers:
return jsonify({'error': f'Required column {col} missing'}), 400
return jsonify({"error": f"Required column {col} missing"}), 400
# Process rows
imported = 0
for row in csv_reader:
data = dict(zip(headers, row))
# Remove id to create new record
if 'id' in data:
del data['id']
if "id" in data:
del data["id"]
# Create new instance
instance = model(**data)
db.session.add(instance)
imported += 1
db.session.commit()
return jsonify({'success': f'Imported {imported} records successfully'})
return jsonify({"success": f"Imported {imported} records successfully"})
except Exception as e:
db.session.rollback()
return jsonify({'error': str(e)}), 500
return jsonify({"error": str(e)}), 500