from flask import Blueprint, render_template, redirect, url_for, flash, request, abort, current_app from flask_login import current_user, login_required from werkzeug.utils import secure_filename from app import db from models import User, Topic, Post from forms import EditProfileForm, ChangePasswordForm import os from datetime import datetime import logging from PIL import Image import uuid # Set up logger logger = logging.getLogger(__name__) # Create blueprint user_bp = Blueprint('user', __name__, url_prefix='/user') def save_avatar(avatar_file): """Save the avatar image and return the filename""" # Generate a unique filename filename = secure_filename(f"{uuid.uuid4().hex[:8]}_{avatar_file.filename}") # Define the upload path upload_dir = os.path.join(current_app.static_folder, 'uploads', 'avatars') filepath = os.path.join(upload_dir, filename) # Resize and save the image img = Image.open(avatar_file) img.thumbnail((150, 150)) # Resize to max dimensions while preserving aspect ratio img.save(filepath) return filename @user_bp.route('/profile/') def profile(username): user = User.query.filter_by(username=username).first_or_404() # Get user's topics with pagination page = request.args.get('page', 1, type=int) per_page = 10 topics = Topic.query.filter_by(author_id=user.id)\ .order_by(Topic.created_at.desc())\ .paginate(page=page, per_page=per_page, error_out=False) # Get user's recent posts recent_posts = Post.query.filter_by(author_id=user.id)\ .order_by(Post.created_at.desc())\ .limit(5)\ .all() return render_template('user/profile.html', user=user, topics=topics, recent_posts=recent_posts) @user_bp.route('/edit_profile', methods=['GET', 'POST']) @login_required def edit_profile(): form = EditProfileForm() if form.validate_on_submit(): # Update user profile if form.avatar.data: try: filename = save_avatar(form.avatar.data) current_user.avatar = filename except Exception as e: logger.error(f"Avatar upload error: {str(e)}") flash('Une erreur est survenue lors du téléchargement de votre avatar.', 'danger') current_user.signature = form.signature.data current_user.location = form.location.data current_user.website = form.website.data current_user.bio = form.bio.data db.session.commit() flash('Votre profil a été mis à jour !', 'success') return redirect(url_for('user.profile', username=current_user.username)) # Pre-fill form with current user data if request.method == 'GET': form.signature.data = current_user.signature form.location.data = current_user.location form.website.data = current_user.website form.bio.data = current_user.bio return render_template('user/edit_profile.html', form=form) @user_bp.route('/change_password', methods=['GET', 'POST']) @login_required def change_password(): form = ChangePasswordForm() if form.validate_on_submit(): # Check if current password is correct if not current_user.check_password(form.current_password.data): flash('Le mot de passe actuel est incorrect.', 'danger') return render_template('user/change_password.html', form=form) # Update password current_user.set_password(form.password.data) db.session.commit() flash('Votre mot de passe a été mis à jour !', 'success') return redirect(url_for('user.profile', username=current_user.username)) return render_template('user/change_password.html', form=form) @user_bp.route('/posts') @login_required def user_posts(): page = request.args.get('page', 1, type=int) per_page = 20 posts = Post.query.filter_by(author_id=current_user.id)\ .order_by(Post.created_at.desc())\ .paginate(page=page, per_page=per_page, error_out=False) return render_template('user/posts.html', posts=posts)