flask.py文件
from flask import Flask, render_template, request, redirect, url_for, flash, session
from flask_mysqldb import MySQL
import bcrypt
app = Flask(__name__)
app.secret_key = "secret"
# MySQL configurations
app.config['MYSQL_HOST'] = 'localhost'
app.config['MYSQL_USER'] = 'root'
app.config['MYSQL_PASSWORD'] = 'password'
app.config['MYSQL_DB'] = 'users'
mysql = MySQL(app)
@app.route('/')
def home():
return render_template('home.html')
@app.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'POST' and 'email' in request.form and 'password' in request.form:
email = request.form['email']
password = request.form['password'].encode('utf-8')
cur = mysql.connection.cursor()
cur.execute('SELECT * FROM accounts WHERE email = %s', (email,))
account = cur.fetchone()
cur.close()
if account:
if bcrypt.hashpw(password, account[2].encode('utf-8')) == account[2].encode('utf-8'):
session['loggedin'] = True
session['id'] = account[0]
session['email'] = account[1]
flash('You have been logged in!', 'success')
return redirect(url_for('dashboard'))
else:
flash('Incorrect password!', 'danger')
else:
flash('Email not found!', 'danger')
return render_template('login.html')
@app.route('/register', methods=['GET', 'POST'])
def register():
if request.method == 'POST' and 'email' in request.form and 'password' in request.form:
email = request.form['email']
password = request.form['password'].encode('utf-8')
hashed_password = bcrypt.hashpw(password, bcrypt.gensalt())
cur = mysql.connection.cursor()
cur.execute('SELECT * FROM accounts WHERE email = %s', (email,))
account = cur.fetchone()
if account:
flash('Email already exists!', 'danger')
else:
cur.execute('INSERT INTO accounts VALUES (NULL, %s, %s)', (email, hashed_password,))
mysql.connection.commit()
flash('You have successfully registered!', 'success')
return redirect(url_for('login'))
cur.close()
return render_template('register.html')
@app.route('/dashboard')
def dashboard():
if 'loggedin' in session:
return render_template('dashboard.html', email=session['email'])
return redirect(url_for('login'))
@app.route('/logout')
def logout():
session.pop('loggedin', None)
session.pop('id', None)
session.pop('email', None)
flash('You have been logged out!', 'success')
return redirect(url_for('login'))
@app.route('/change-password', methods=['GET', 'POST'])
def change_password():
if 'loggedin' in session:
if request.method == 'POST' and 'current_password' in request.form and 'new_password' in request.form:
current_password = request.form['current_password'].encode('utf-8')
new_password = request.form['new_password'].encode('utf-8')
cur = mysql.connection.cursor()
cur.execute('SELECT * FROM accounts WHERE id = %s', (session['id'],))
account = cur.fetchone()
if bcrypt.hashpw(current_password, account[2].encode('utf-8')) == account[2].encode('utf-8'):
hashed_new_password = bcrypt.hashpw(new_password, bcrypt.gensalt())
cur.execute('UPDATE accounts SET password = %s WHERE id = %s', (hashed_new_password, session['id'],))
mysql.connection.commit()
flash('Password changed successfully!', 'success')
else:
flash('Incorrect password!', 'danger')
return render_template('change_password.html')
return redirect(url_for('login'))
if __name__ == '__main__':
app.run(debug=True)
HTML文件:
home.html:
复制{% extends 'base.html' %}
{% block content %}
<h1>Welcome to my Flask App!</h1>
{% endblock %}
base.html:
复制<!doctype html>
<html>
<head>
<title>Flask App</title>
<link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}">
</head>
<body>
<div class="container">
<header>
<nav>
<ul>
<li><a href="{{ url_for('home') }}">Home</a></li>
{% if session.loggedin %}
<li><a href="{{ url_for('dashboard') }}">Dashboard</a></li>
<li><a href="{{ url_for('logout') }}">Logout</a></li>
{% else %}
<li><a href="{{ url_for('login') }}">Login</a></li>
<li><a href="{{ url_for('register') }}">Register</a></li>
{% endif %}
</ul>
</nav>
</header>
{% with messages = get_flashed_messages() %}
{% if messages %}
<ul class="flashes">
{% for message in messages %}
<li>{{ message }}</li>
{% endfor %}
</ul>
{% endif %}
{% endwith %}
{% block content %}{% endblock %}
</div>
<script src="{{ url_for('static', filename='js/script.js') }}"></script>
</body>
</html>
login.html:
复制{% extends 'base.html' %}
{% block content %}
<h1>Login</h1>
<form method="POST">
<div>
<label for="email">Email</label>
<input type="email" name="email" id="email" required>
</div>
<div>
<label for="password">Password</label>
<input type="password" name="password" id="password" required>
</div>
<button type="submit">Login</button>
</form>
{% endblock %}
register.html:
复制{% extends 'base.html' %}
{% block content %}
<h1>Register</h1>
<form method="POST">
<div>
<label for="email">Email</label>
<input type="email" name="email" id="email" required>
</div>
<div>
<label for="password">Password</label>
<input type="password" name="password" id="password" required>
</div>
<button type="submit">Register</button>
</form>
{% endblock %}
dashboard.html:
复制{% extends 'base.html' %}
{% block content %}
<h1>Welcome, {{ email }}!</h1>
{% endblock %}
change_password.html:
复制{% extends 'base.html' %}
{% block content %}
<h1>Change Password</h1>
<form method="POST">
<div>
<label for="current_password">Current Password</label>
<input type="password" name="current_password" id="current_password" required>
</div>
<div>
<label for="new_password">New Password</label>
<input type="password" name="new_password" id="new_password" required>
</div>
<button type="submit">Change Password</button>
</form>
{% endblock %}
CSS文件:
复制.container {
max-width: 800px;
margin: 0 auto;
padding: 0 20px;
}
header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
}
nav ul {
display: flex;
list-style: none;
margin: 0;
padding: 0;
}
nav ul li {
margin: 0 10px;
}
nav ul li a {
color: #333;
text-decoration: none;
}
nav ul li a:hover {
text-decoration: underline;
}
.flashes {
list-style: none;
margin: 0;
padding: 0;
}
.flashes li {
margin-bottom: 10px;
padding: 10px;
border-radius: 5px;
}
.success {
background-color: #d4edda;
color: #155724;
border: 1px solid #c3e6cb;
}
.danger {
background-color: #f8d7da;
color: #721c24;
border: 1px solid #f5c6cb;
}
JavaScript文件:
复制// nothing here for now