Files
finance_app/app.py
anton 7d00cf062e Changes to be committed:
modified:   app.py
	modified:   init_db.py
	modified:   static/styles.css
	modified:   templates/index.html
	new file:   templates/login.html
	new file:   templates/register.html
2025-07-02 15:04:21 +03:00

164 lines
6.5 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import os
from flask import Flask, render_template, request, redirect, url_for, flash, session
from flask_sqlalchemy import SQLAlchemy
from werkzeug.security import generate_password_hash, check_password_hash
from datetime import datetime, date
from dotenv import load_dotenv
from functools import wraps
load_dotenv()
app = Flask(__name__)
app.secret_key = os.getenv('SECRET_KEY', 'supersecretkey')
app.config['SQLALCHEMY_DATABASE_URI'] = os.getenv('DATABASE_URL', 'postgresql://user:password@localhost/finance_db')
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db = SQLAlchemy(app)
# Модель пользователя
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(80), unique=True, nullable=False)
email = db.Column(db.String(120), unique=True, nullable=False)
password = db.Column(db.String(200), nullable=False)
created_at = db.Column(db.DateTime, default=datetime.utcnow)
def set_password(self, password):
self.password = generate_password_hash(password)
def check_password(self, password):
return check_password_hash(self.password, password)
# Модель транзакции (обновлена с привязкой к пользователю)
class Transaction(db.Model):
id = db.Column(db.Integer, primary_key=True)
user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
type = db.Column(db.String(10), nullable=False)
amount = db.Column(db.Float, nullable=False)
category = db.Column(db.String(50), nullable=False)
date = db.Column(db.Date, nullable=False, default=date.today())
description = db.Column(db.Text)
user = db.relationship('User', backref=db.backref('transactions', lazy=True))
# Декоратор для проверки аутентификации
def login_required(f):
@wraps(f)
def decorated_function(*args, **kwargs):
if 'user_id' not in session:
flash('Пожалуйста, войдите в систему для доступа к этой странице', 'warning')
return redirect(url_for('login'))
return f(*args, **kwargs)
return decorated_function
# Регистрация пользователя
@app.route('/register', methods=['GET', 'POST'])
def register():
if request.method == 'POST':
username = request.form['username']
email = request.form['email']
password = request.form['password']
confirm_password = request.form['confirm_password']
# Проверки
if password != confirm_password:
flash('Пароли не совпадают', 'danger')
return redirect(url_for('register'))
if User.query.filter_by(username=username).first():
flash('Это имя пользователя уже занято', 'danger')
return redirect(url_for('register'))
if User.query.filter_by(email=email).first():
flash('Этот email уже используется', 'danger')
return redirect(url_for('register'))
# Создание пользователя
new_user = User(username=username, email=email)
new_user.set_password(password)
db.session.add(new_user)
db.session.commit()
flash('Регистрация успешна! Теперь вы можете войти', 'success')
return redirect(url_for('login'))
return render_template('register.html')
# Вход в систему
@app.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'POST':
username = request.form['username']
password = request.form['password']
remember = 'remember' in request.form
user = User.query.filter_by(username=username).first()
if user and user.check_password(password):
session['user_id'] = user.id
session['username'] = user.username
flash('Вы успешно вошли в систему!', 'success')
return redirect(url_for('index'))
flash('Неверное имя пользователя или пароль', 'danger')
return render_template('login.html')
# Выход из системы
@app.route('/logout')
@login_required
def logout():
session.pop('user_id', None)
session.pop('username', None)
flash('Вы успешно вышли из системы', 'info')
return redirect(url_for('login'))
# Главная страница (требует аутентификации)
@app.route('/')
@login_required
def index():
user_id = session['user_id']
transactions = Transaction.query.filter_by(user_id=user_id).order_by(Transaction.date.desc()).all()
total_income = sum(t.amount for t in transactions if t.type == 'income')
total_expense = sum(t.amount for t in transactions if t.type == 'expense')
balance = total_income - total_expense
categories = {}
for t in transactions:
if t.category not in categories:
categories[t.category] = {'income': 0, 'expense': 0}
categories[t.category][t.type] += t.amount
return render_template('index.html',
transactions=transactions,
total_income=total_income,
total_expense=total_expense,
balance=balance,
categories=categories,
current_date=date.today(),
username=session['username'])
# Остальные роуты (add, edit, delete) аналогично защищаем @login_required
# и добавляем user_id при создании/редактировании транзакций
@app.route('/add', methods=['GET', 'POST'])
@login_required
def add_transaction():
if request.method == 'POST':
user_id = session['user_id']
# ... остальной код ...
new_transaction = Transaction(
user_id=user_id, # Добавляем привязку к пользователю
# ... остальные поля ...
)
# ... сохранение ...
return render_template('add.html', current_date=date.today())
# Аналогично для edit и delete добавляем проверку, что пользователь редактирует свою транзакцию
if __name__ == '__main__':
with app.app_context():
db.create_all()
app.run(debug=True)