- version : 0.3
- description : make the UI with arabic and trying to add importing from .csv feature .
هذا الالتزام موجود في:
147
app.py
147
app.py
@@ -1,26 +1,28 @@
|
||||
import sqlite3
|
||||
import csv
|
||||
import io
|
||||
# The 'flash' import is no longer needed
|
||||
from flask import Flask, render_template, request, redirect, url_for
|
||||
|
||||
# Create a Flask application instance
|
||||
app = Flask(__name__)
|
||||
# The 'secret_key' is no longer required as we are not using flash/sessions
|
||||
# app.secret_key = 'your_super_secret_key_12345'
|
||||
|
||||
|
||||
# --- Database Functions ---
|
||||
|
||||
def get_db_connection():
|
||||
"""Creates and returns a connection to the SQLite database."""
|
||||
conn = sqlite3.connect('students.db')
|
||||
# Return rows as dictionaries, so we can access columns by name
|
||||
conn.row_factory = sqlite3.Row
|
||||
return conn
|
||||
|
||||
def init_db():
|
||||
"""Initializes the database and creates the 'students' table if it doesn't exist."""
|
||||
"""Initializes the database. THIS IS ONLY RUN MANUALLY from the command line."""
|
||||
conn = get_db_connection()
|
||||
# Use a 'with' statement to automatically handle closing the connection
|
||||
with conn:
|
||||
# Drop the table if it exists to ensure the new schema is applied
|
||||
conn.execute('DROP TABLE IF EXISTS students')
|
||||
# Create the table with the new, expanded schema
|
||||
conn.execute('''
|
||||
CREATE TABLE students (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
@@ -38,10 +40,9 @@ def init_db():
|
||||
''')
|
||||
print("Database initialized and 'students' table created with the new schema.")
|
||||
|
||||
# Command to initialize the database from the command line: flask init-db
|
||||
@app.cli.command('init-db')
|
||||
def init_db_command():
|
||||
"""Clear existing data and create new tables."""
|
||||
"""Clears existing data and creates new tables."""
|
||||
init_db()
|
||||
|
||||
|
||||
@@ -49,43 +50,119 @@ def init_db_command():
|
||||
|
||||
@app.route('/')
|
||||
def index():
|
||||
"""Renders the main page with the list of students."""
|
||||
"""Renders the main page and displays any messages passed in the URL."""
|
||||
# Get the message from the URL query parameters
|
||||
message = request.args.get('message', None)
|
||||
category = request.args.get('category', None)
|
||||
|
||||
conn = get_db_connection()
|
||||
# Select all columns to display in the table
|
||||
students = conn.execute('SELECT * FROM students ORDER BY id').fetchall()
|
||||
conn.close()
|
||||
# The 'students' variable is passed to the HTML template
|
||||
return render_template('index.html', students=students)
|
||||
|
||||
# Pass the message and students to the template
|
||||
return render_template('index.html', students=students, message=message, category=category)
|
||||
|
||||
@app.route('/add', methods=['POST'])
|
||||
def add_student():
|
||||
"""Handles the form submission for adding a new student."""
|
||||
# Get all the new data from the form submitted in index.html
|
||||
student_name = request.form['student_name']
|
||||
age = request.form['age']
|
||||
parent_name = request.form['parent_name']
|
||||
parent_phone_1 = request.form['parent_phone_1']
|
||||
parent_phone_2 = request.form.get('parent_phone_2') # .get() for optional fields
|
||||
student_phone = request.form.get('student_phone') # .get() for optional fields
|
||||
grade = request.form['grade']
|
||||
school_name = request.form['school_name']
|
||||
address = request.form['address']
|
||||
memorizing = request.form['memorizing']
|
||||
"""Handles the form submission for adding a single new student."""
|
||||
try:
|
||||
student_name = request.form['student_name']
|
||||
age = request.form['age']
|
||||
parent_name = request.form['parent_name']
|
||||
parent_phone_1 = request.form['parent_phone_1']
|
||||
parent_phone_2 = request.form.get('parent_phone_2')
|
||||
student_phone = request.form.get('student_phone')
|
||||
grade = request.form['grade']
|
||||
school_name = request.form['school_name']
|
||||
address = request.form['address']
|
||||
memorizing = request.form['memorizing']
|
||||
|
||||
if not all([student_name, age, parent_name, parent_phone_1, grade, school_name, address, memorizing]):
|
||||
# Instead of flashing, redirect with a message
|
||||
return redirect(url_for('index', message='الرجاء تعبئة جميع الحقول المطلوبة.', category='danger'))
|
||||
|
||||
conn = get_db_connection()
|
||||
conn.execute('''
|
||||
INSERT INTO students (student_name, age, parent_name, parent_phone_1, parent_phone_2, student_phone, grade, school_name, address, memorizing)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
''', (student_name, age, parent_name, parent_phone_1, parent_phone_2, student_phone, grade, school_name, address, memorizing))
|
||||
conn.commit()
|
||||
conn.close()
|
||||
|
||||
message = 'تمت إضافة الطالب الجديد بنجاح!'
|
||||
category = 'success'
|
||||
except Exception as e:
|
||||
message = f'حدث خطأ أثناء إضافة الطالب: {e}'
|
||||
category = 'danger'
|
||||
|
||||
# Insert the new student record into the database with all fields
|
||||
conn = get_db_connection()
|
||||
conn.execute('''
|
||||
INSERT INTO students (student_name, age, parent_name, parent_phone_1, parent_phone_2, student_phone, grade, school_name, address, memorizing)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
''', (student_name, age, parent_name, parent_phone_1, parent_phone_2, student_phone, grade, school_name, address, memorizing))
|
||||
conn.commit()
|
||||
conn.close()
|
||||
return redirect(url_for('index', message=message, category=category))
|
||||
|
||||
@app.route('/import', methods=['POST'])
|
||||
def import_csv():
|
||||
"""Handles CSV import and redirects with a status message in the URL."""
|
||||
if 'file' not in request.files or request.files['file'].filename == '':
|
||||
return redirect(url_for('index', message='لم يتم اختيار أي ملف.', category='danger'))
|
||||
|
||||
file = request.files['file']
|
||||
|
||||
if file and file.filename.endswith('.csv'):
|
||||
students_to_add = [] # This is our "2D vector"
|
||||
try:
|
||||
stream = io.StringIO(file.stream.read().decode("utf-8-sig"), newline=None)
|
||||
csv_reader = csv.reader(stream)
|
||||
|
||||
# First, read all rows from CSV into the students_to_add list
|
||||
for i, row in enumerate(csv_reader, start=1):
|
||||
if len(row) != 10:
|
||||
msg = f'خطأ في ملف CSV في السطر رقم {i}: يجب أن يحتوي السطر على 10 أعمدة.'
|
||||
return redirect(url_for('index', message=msg, category='danger'))
|
||||
try:
|
||||
# Validate and prepare the row data
|
||||
student_data = (
|
||||
row[0], int(row[1]), row[2], row[3],
|
||||
row[4] if row[4] else None, row[5] if row[5] else None,
|
||||
row[6], row[7], row[8], row[9]
|
||||
)
|
||||
students_to_add.append(student_data)
|
||||
except ValueError:
|
||||
msg = f"خطأ في ملف CSV في السطر رقم {i}: يجب أن يكون العمر (العمود الثاني) رقماً."
|
||||
return redirect(url_for('index', message=msg, category='danger'))
|
||||
|
||||
# If the list was successfully built, proceed to add to the database
|
||||
if students_to_add:
|
||||
conn = get_db_connection()
|
||||
# Use a try/except block for the database operation
|
||||
try:
|
||||
# Now, loop through the "2D vector" and add each student one by one
|
||||
for student in students_to_add:
|
||||
conn.execute('''
|
||||
INSERT INTO students (student_name, age, parent_name, parent_phone_1, parent_phone_2, student_phone, grade, school_name, address, memorizing)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
''', student)
|
||||
|
||||
# If all insertions succeed, commit them to the database
|
||||
conn.commit()
|
||||
message = f'تم استيراد وإضافة {len(students_to_add)} طالب بنجاح!'
|
||||
category = 'success'
|
||||
except sqlite3.Error as e:
|
||||
# If any error occurs during insertion, the transaction is rolled back automatically
|
||||
message = f'حدث خطأ في قاعدة البيانات أثناء الإضافة: {e}'
|
||||
category = 'danger'
|
||||
finally:
|
||||
# Always close the connection
|
||||
conn.close()
|
||||
else:
|
||||
message = 'ملف CSV فارغ أو لا يمكن معالجته.'
|
||||
category = 'warning'
|
||||
|
||||
except Exception as e:
|
||||
message = f'حدث خطأ غير متوقع أثناء عملية الاستيراد: {e}'
|
||||
category = 'danger'
|
||||
|
||||
return redirect(url_for('index', message=message, category=category))
|
||||
else:
|
||||
return redirect(url_for('index', message='صيغة الملف غير صالحة. الرجاء رفع ملف .csv فقط.', category='danger'))
|
||||
|
||||
# Redirect back to the main page to see the updated list
|
||||
return redirect(url_for('index'))
|
||||
|
||||
if __name__ == '__main__':
|
||||
# You can remove the init_db() call from here if you are using the flask command
|
||||
# It's good practice to manage the DB initialization separately.
|
||||
app.run(debug=True)
|
||||
|
||||
المرجع في مشكلة جديدة
حظر مستخدم