csv upload

This commit is contained in:
2025-06-08 17:47:49 +02:00
parent ab9e07f29b
commit f71cb7d24a
2 changed files with 167 additions and 2 deletions

156
app.py
View File

@@ -1,4 +1,4 @@
from flask import Flask, render_template, request, redirect, url_for, flash, session, jsonify
from flask import Flask, render_template, request, redirect, url_for, flash, session, jsonify, Response
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate
from datetime import datetime
@@ -7,6 +7,8 @@ from werkzeug.utils import secure_filename
import os
from config import Config
import random
import csv
import io
app = Flask(__name__)
app.config.from_object(Config)
@@ -1453,6 +1455,158 @@ def recognize_plant():
random_plant = random.choice(plants)
return jsonify({'redirect': url_for('plant', plant_id=random_plant.id)})
@app.route('/admin/plants/upload-csv', methods=['POST'])
def upload_plants_csv():
if not is_logged_in():
return redirect(url_for('login'))
if 'csv_file' not in request.files:
flash('No file uploaded', 'error')
return redirect(url_for('manage_plants'))
file = request.files['csv_file']
if file.filename == '':
flash('No file selected', 'error')
return redirect(url_for('manage_plants'))
if not file.filename.endswith('.csv'):
flash('Please upload a CSV file', 'error')
return redirect(url_for('manage_plants'))
try:
# Read the CSV file
stream = io.StringIO(file.stream.read().decode("UTF8"), newline=None)
csv_reader = csv.DictReader(stream)
# Get all the lookup dictionaries
climates = {c.name.lower(): c.id for c in Climate.query.all()}
environments = {e.name.lower(): e.id for e in Environment.query.all()}
lights = {l.name.lower(): l.id for l in Light.query.all()}
toxicities = {t.name.lower(): t.id for t in Toxicity.query.all()}
sizes = {s.name.lower(): s.id for s in Size.query.all()}
care_difficulties = {d.name.lower(): d.id for d in CareDifficulty.query.all()}
growth_rates = {r.name.lower(): r.id for r in GrowthRate.query.all()}
products = {p.name.lower(): p.id for p in Product.query.all()}
success_count = 0
error_count = 0
duplicate_count = 0
for row in csv_reader:
try:
# Check if plant with this name already exists
existing_plant = Plant.query.filter_by(name=row['name']).first()
if existing_plant:
duplicate_count += 1
continue
# Create new plant
plant = Plant(
name=row['name'],
description=row.get('description', ''),
care_guide=row.get('care_guide', ''),
date_added=datetime.utcnow()
)
# Set relationships using the lookup dictionaries
if row.get('climate'):
plant.climate_id = climates.get(row['climate'].lower())
if row.get('environment'):
plant.environment_id = environments.get(row['environment'].lower())
if row.get('light'):
plant.light_id = lights.get(row['light'].lower())
if row.get('toxicity'):
plant.toxicity_id = toxicities.get(row['toxicity'].lower())
if row.get('size'):
plant.size_id = sizes.get(row['size'].lower())
if row.get('care_difficulty'):
plant.care_difficulty_id = care_difficulties.get(row['care_difficulty'].lower())
if row.get('growth_rate'):
plant.growth_rate_id = growth_rates.get(row['growth_rate'].lower())
# Handle products (comma-separated list)
if row.get('products'):
product_ids = []
for product_name in row['products'].split(','):
product_name = product_name.strip().lower()
if product_name in products:
product_ids.append(str(products[product_name]))
plant.products = ','.join(product_ids)
db.session.add(plant)
success_count += 1
except Exception as e:
error_count += 1
print(f"Error processing row: {row}, Error: {str(e)}")
continue
db.session.commit()
message = f'Successfully imported {success_count} plants.'
if duplicate_count > 0:
message += f' {duplicate_count} duplicate plants were skipped.'
if error_count > 0:
message += f' {error_count} errors occurred.'
flash(message, 'success')
except Exception as e:
flash(f'Error processing CSV file: {str(e)}', 'error')
db.session.rollback()
return redirect(url_for('manage_plants'))
@app.route('/admin/plants/download-template')
def download_plants_template():
if not is_logged_in():
return redirect(url_for('login'))
# Create a CSV template with headers and example data
output = io.StringIO()
writer = csv.writer(output)
# Write headers
headers = [
'name',
'description',
'care_guide',
'climate',
'environment',
'light',
'toxicity',
'size',
'care_difficulty',
'growth_rate',
'products'
]
writer.writerow(headers)
# Write example row with available options
example_row = [
'Monstera Deliciosa', # name
'Beautiful tropical plant with distinctive leaf holes', # description
'Water weekly, mist leaves occasionally', # care_guide
', '.join([c.name for c in Climate.query.all()]), # climate options
', '.join([e.name for e in Environment.query.all()]), # environment options
', '.join([l.name for l in Light.query.all()]), # light options
', '.join([t.name for t in Toxicity.query.all()]), # toxicity options
', '.join([s.name for s in Size.query.all()]), # size options
', '.join([d.name for d in CareDifficulty.query.all()]), # care_difficulty options
', '.join([r.name for r in GrowthRate.query.all()]), # growth_rate options
', '.join([p.name for p in Product.query.all()]) # product options
]
writer.writerow(example_row)
# Create the response
output.seek(0)
return Response(
output,
mimetype='text/csv',
headers={
'Content-Disposition': 'attachment; filename=plants_template.csv',
'Content-Type': 'text/csv',
}
)
if __name__ == "__main__":
with app.app_context():
db.create_all() # Create all tables