概要
Flaskでログイン画面を実装するときの覚え書き。
ファイル構成
.
├── Dockerfile
├── __init__.py
├── app.py
├── models
│ ├── __init__.py
│ └── models.py
├── requirements.txt
└── templates
├── __init__.py
├── index.html
├── login.html
└── signup.html
models.py
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_login import LoginManager, UserMixin
app = Flask(__name__,template_folder='../templates')
app.config['SQLALCHEMY_DATABASE_URI']= 'postgresql://postgres:password@10.20.1.13:5432/test'
app.config['SECRET_KEY'] = os.urandom(24)
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
app.config['SQLALCHEMY_ECHO']=True
db = SQLAlchemy(app)
login_manager = LoginManager()
login_manager.init_app(app)
class User(UserMixin, db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.Text, nullable=False, unique=True)
password = db.Column(db.Text)
login.html
{% extends 'index.html' %}
{% block content %}
<h1>ログイン画面</h1>
<form method="POST">
<label for="">ユーザ名</label>
<input type="text" name="username" required>
<label for="">パスワード</label>
<input type="password" name="password" required>
<input type="submit" value="ログイン">
{% if error_message %}
<p style="color: red;">{{ error_message }}</p>
{% endif %}
<br><br>
<a href='/signup'>戻る</a>
</form>
{% endblock %}
signup.html
{% extends 'index.html' %}
{% block content %}
<h1>ユーザ登録</h1>
<form method="POST">
<label for="">ユーザ名</label>
<input type="text" name="username" required>
<label for="">パスワード</label>
<input type="password" name="password" required>
<input type="submit" value="サインイン">
{% if error_message %}
<p style="color: red;">{{ error_message }}</p>
{% endif %}
<br><br>
<a href='/login'>ログインはこちら</a>
</form>
{% endblock %}
index.html
{% block content %}
<html lang="jp">
<head>
<meta charset="UTF-8">
<title>テスト</title>
</head>
<body>
<a href="/logout" role="button">ログアウト</a>
</body>
</html>
{% endblock %}
app.html
from models.models import db, app, login_manager
from flask import render_template, request, redirect
from flask_login import login_user, logout_user, login_required
from werkzeug.security import generate_password_hash, check_password_hash
@login_manager.unauthorized_handler
def unauthorized():
return redirect('/signup')
@login_manager.user_loader
def load_user(user_id):
return User.query.get(int(user_id))
@app.route('/logout')
@login_required
def logout():
logout_user()
return redirect('/login')
@app.route('/login', methods=['GET', 'POST'])
def login():
if request.method == "POST":
username = request.form.get('username')
password = request.form.get('password')
user = User.query.filter_by(username=username).first()
if not user:
return render_template('login.html', error_message='登録されていません')
if check_password_hash(user.password, password):
login_user(user)
return redirect('/')
else:
return render_template('login.html')
@app.route('/signup', methods=['GET', 'POST'])
def signup():
if request.method == "POST":
username = request.form.get('username')
password = request.form.get('password')
user = User.query.filter_by(username=username).first()
if user:
return render_template('signup.html', error_message='既に使われているユーザー名です')
user = User(username=username, password=generate_password_hash(password, method='sha256'))
db.session.add(user)
db.session.commit()
return redirect('/login')
else:
return render_template('signup.html')
@app.route('/', methods=['GET','POST'])
@login_required
def index():
"""省略"""
return render_template('index.html', test = test)
if __name__ == '__main__':
app.debug = True
app.run(debug=True, host='0.0.0.0', port=5003)