【第8回】FlaskでWebアプリ作成練習。ログイン機能(だけ)を実装しよう。
こんにちは(@t_kun_kamakiri)
前回↓に引き続き、「Flask」の勉強を進めていきたいと思います。
ちょっとFlaskの勉強の期間が空いたのですが、時間がたっぷりできたのでちょっとずつ勉強を再開しています。
FlaskといえばPythonを使ってWebブラウザを操作するフレームワークですが、結構簡単に使うことができます。
僕自身は、本日が「第8回」なので8日間くらいしか勉強していないという事ですが、ログイン機能(ログイン機能しかない)くらいなら実装することができます。
今日やるのは「Flaskを使ってログイン機能を実装する」です。
イメージは以下のです。
●idとパスワードを入力する
●はじめて入力するidだったら新規追加とする。
この時データを辞書型として追加していく。
●同じidを入力した場合、前回入力したパスワードと一致していない場合は「パスワードが間違っています」と警告を出す。
超シンプルで、ログイン機能以外何もない(何の役にも立たない)ものですが、Flaskの勉強にはとても理解がしやすいと思います。
他の言語でも簡単にできる(例えばPHPとか)のですが、今後Pythonのライブラリを使いたいのでWebと連携して勉強するためにFlaskを使って感覚を養う目的です。
では、少しずつコードを書きながら解説します。
☟こちらの参考書で勉強しています。
ファイル構成
全体のファイル構成は以下のようにしておきます。
--templates
|--layout.html
|--login.html
--static
|--style.css
run.py
●「run.py」がPythonのコード
●「~.html」がhtmlのファイル
●「style.css」がCSSのファイル(今回は使っていません)
ログイン画面のhtmlを用意する
まずは、ログイン画面用のhtmlを用意しておきます。
ここでは、ページアウトのレイアウトを継承するでも紹介したように、htmlのテンプレートを用意しておきます。
layout.html
<!doctype html>
<html lang="ja">
<head>
<title>{% block title %}{% endblock %}</title>
<meta charset="utf-8"/>
<link rel="stylesheet"
href="{{url_for('static', filename='style.css')}}">
</head>
<body>
<h1>{% block headline %}{% endblock %}</h1>
{% block content %}{% endblock %}
<div class="footer">
{% block footer %}{% endblock %}
</div>
</body>
</html>これがhtnlのひな型です。
こちらはテンプレートとして使うだけで実際はほとんど書き換えることはしません。
login.html
{% extends "layout.html" %}
{% block title %}
ログイン
{% endblock %}
{% block headline %}
{{title}}
{% endblock %}
{% block content%}
<p>{{message}}</p>
<form method="post" action="/login">
<table>
<tr>
<th>id</th>
<td>
<input type="text" name="id" value="{{id}}">
</td>
<th>password</th>
<td>
<input type="password" name="pass">
</td>
</tr>
<th></th>
<td>
<input type="submit" value="Login">
</td>
</table>
</form>
{% endblock %}run.py
from flask import Flask, render_template, request, session, redirect
app = Flask(__name__)
app.secret_key = b'random string...'
@app.route('/', methods=['GET'])
def index():
title ="メッセージ"
msg = "はじめてのFlask"
return render_template('login.html', \
title='Messages', \
message=msg)
# return redirect('/')
if __name__ == '__main__':
app.run()ここまででどうなっているのかを確認してみましょう。
$python3 run.py
※実は今日からvisual stdio codeとWSL(Windows上でLinuxを使う)を連携しています。
「http://127.0.0.1:5000/」にアクセスすると以下のようにブラウザ上に表示されます。
ひとまずここまでできました。
試しに「id」と「password」に何か入れてみてください。
エラーが出ると思います。
これはまだPOST処理について何も指定していないからです。
どういう状況かというと、「/」にアクセスがあった場合には「login.html」を表示するようにしています。
そして、「id」と「password」を入力すると入力した変数は黄色枠で囲んだ「"id"」「"pass"」として、formタグのactionで指定している「/login」に変数を返すのです・・・・が、「/login」にアクセスがあったときの処理をPythonで記述していないからエラーが出ました。
「/login」にアクセスがあった場合の処理を書く
run.pyに以下を追加します。(処理は後から書いていきます)
@app.route('/login' , methods=['POST'])
def login_post():これで「/login」にアクセスがあったときの処理を指定できます。
処理の中身ですが、
●新規のidだったらname_listの辞書型に「id」と「pass」を追加する
●既に登録しているidだったらパスワードが一致しているかを確認する
●既に登録しているidでパスワードが一致しなかった場合は、「パスワードが一致していません」と警告を出す
という場合分けをします。
全体の「run.py」を書いておきます。
from flask import Flask, render_template, request, session, redirect
app = Flask(__name__)
app.secret_key = b'random string...'
name_list = {}
@app.route('/', methods=['GET'])
def index():
global name_list
title ="メッセージ"
msg = "はじめてのFlask"
return render_template('login.html', \
title='Messages', \
message=msg,
name = name_list)
return redirect('/')
@app.route('/login' , methods=['POST'])
def login_post():
global name_list
id = request.form.get('id')
pwd = request.form.get('pass')
#idが既にあるかどうかを確認する
if id in name_list:
#IDとpasswordが一致しているかを確認する。
if pwd == name_list[id]:
#ログイン可能な状態にする
session['flag'] = True
#IDとpasspwrdが一致しない場合は
else:
session['flag'] = False
#idの新規登録の場合
else:
name_list[id] = pwd
session['flag'] = True #ログイン可能な状態にする
session['id'] = id
user_id = session.get("id")
#idとpasseprdが一致するかどうかの確認
if session['flag']: #一致した場合
return redirect('/')
else: #一致しなかった場合
title = 'ログイン'
msg = 'パスワードが間違っています'
return render_template('login.html',\
title = title,\
message = msg,\
name = name_list,\
user_id=user_id)
if __name__ == '__main__':
# app.run(debug=True)
app.run()●●新規のidだったらname_listの辞書型に「id」と「pass」を追加する
if id in name_list:で確認します。
ちょっとわかりにくいので、別のファイルとかでPythonコードを以下のように書いて確認をしてみればわかります。
id = 'kamakiri'
name_list = {
'kamakiri':'kkkk',
'yamada':'kkga',
'suzuki':'aaaa'
}
if id in name_list:
print(id)
#結果
kamakiri「id = 'kamakiri'」が「name_list」の中に存在していれば、name_listのキーを返してくれます。
もし、新規のidだったら辞書型に追加するようにします。
id = 'apple'
id_pass = 'apple_pwd'
name_list = {
'kamakiri':'kkk',
'yamada':'kkga',
'suzuki':'aaaa'
}
if id in name_list:
print(id)
else:
name_list[id] = id_pass
print(name_list)
#結果
{'kamakiri': 'kkk', 'yamada': 'kkga', 'suzuki': 'aaaa', 'apple': 'apple_pwd'}さらに、flaskのsessionを使えば、session[キー] = 値という形で、キーと値を保管することができます。
以下のものだけを指定しています。
●session['flag'] = True ←ログイン可能かどうかの判断
●session['id'] = id ←idをWebサーバー上に一旦保存しておく
※こうすることで違うブラウザ上でアクセスしてもidが保存されているので、ユーザー間でidが被ることはありません。
●既に登録しているidだったらパスワードが一致しているかを確認する
#IDとpasswordが一致しているかを確認する。
if pwd == name_list[id]:
#ログイン可能な状態にする
session['flag'] = True
#IDとpasspwrdが一致しない場合は
else:
session['flag'] = False session['flag'] のフラグが「True」か「False」だけでログイン可能かどうかの確認を行っています。
●既に登録しているidでパスワードが一致しなかった場合は、「パスワードが一致していません」と警告を出す
if session['flag']: #一致した場合
return redirect('/')
else: #一致しなかった場合
title = 'ログイン'
msg = 'パスワードが間違っています'
return render_template('login.html',\
title = title,\
message = msg,\
name = name_list,\
user_id=user_id)「id」と「パスワード」が一致していたら無事ログインが可能ということで「return redirect('/')」にアクセスを返しています。
今は、
@app.route('/', methods=['GET'])
def index():
の処理が実行されるだけです。
「id」と「パスワード」が一致していなかったら、
title = 'ログイン'
msg = 'パスワードが間違っています'
return render_template('login.html',\
title = title,\
message = msg,\
name = name_list,\
user_id=user_id)という処理が実行されます。
ここで使われている「name_list」や「session」がわかりにくいのでWeb上に出力してどういう風に動作しているのかを確認してみます。
●「 session['id'] = id」でsessionの'id'というキーに「login.html」から取得したidという値をすることができて、
●「user_id = session.get("id")」とすると、sessionの'id'に対応した値を取得できます。今は、それをuser_idに代入しています。
session['id'] = id
user_id = session.get("id")これをlogin.htmlが読み込まれたときに値を引き渡せばよいので、
return render_template('login.html',\
title = title,\
message = msg,\
name = name_list,\
user_id=user_id)と書いておきました。
「name 」と「user_id」を「layout.html」に書いておけば、「login.html」の表示の際にWeb上で確認することができます。
layout.html
<h1>{% block headline %}{% endblock %}</h1>
<p>{{name}}</p>
<p>{{user_id}}</p>というわけで完成しました(^^)/
全体のコードを載せておきます
断片的な説明だとわかりにくいと思うので全体のコードを載せておきます。
【ファイル構成】
--templates
|--layout.html
|--login.html
--static
|--style.css
run.py
layout.html
<!doctype html>
<html lang="ja">
<head>
<title>{% block title %}{% endblock %}</title>
<meta charset="utf-8"/>
<link rel="stylesheet"
href="{{url_for('static', filename='style.css')}}">
</head>
<body>
<h1>{% block headline %}{% endblock %}</h1>
<p>{{name}}</p>
<p>{{user_id}}</p>
{% block content %}{% endblock %}
<div class="footer">
{% block footer %}{% endblock %}
</div>
</body>
</html>login.html
{% extends "layout.html" %}
{% block title %}
ログイン
{% endblock %}
{% block headline %}
{{title}}
{% endblock %}
{% block content%}
<p>{{message}}</p>
<form method="post" action="/login">
<table>
<tr>
<th>id</th>
<td>
<input type="text" name="id" value="{{id}}">
</td>
<th>password</th>
<td>
<input type="password" name="pass">
</td>
</tr>
<th></th>
<td>
<input type="submit" value="Login">
</td>
</table>
</form>
{% endblock %}run.py
from flask import Flask, render_template, request, session, redirect
app = Flask(__name__)
app.secret_key = b'random string...'
name_list = {}
@app.route('/', methods=['GET'])
def index():
global name_list
title ="メッセージ"
msg = "はじめてのFlask"
return render_template('login.html', \
title='Messages', \
message=msg,
name = name_list)
return redirect('/')
@app.route('/login' , methods=['POST'])
def login_post():
global name_list
id = request.form.get('id')
pwd = request.form.get('pass')
#idが既にあるかどうかを確認する
if id in name_list:
#IDとpasswordが一致しているかを確認する。
if pwd == name_list[id]:
#ログイン可能な状態にする
session['flag'] = True
#IDとpasspwrdが一致しない場合は
else:
session['flag'] = False
#idの新規登録の場合
else:
name_list[id] = pwd
session['flag'] = True #ログイン可能な状態にする
session['id'] = id
user_id = session.get("id")
#idとpasseprdが一致するかどうかの確認
if session['flag']: #一致した場合
return redirect('/')
else: #一致しなかった場合
title = 'ログイン'
msg = 'パスワードが間違っています'
return render_template('login.html',\
title = title,\
message = msg,\
name = name_list,\
user_id=user_id)
if __name__ == '__main__':
# app.run(debug=True)
app.run()Pythonをじ
$python3 run.py
これで以下のようなWeb上の動作になると思います。
完成です(^^)/
まだまだわかっていないことが多いので、思いもよらない動作をすることがあるかもしれません。
こうやってわかった部分をnoteにまとめていくと理解が深まるので良いですね(^^)
本日でFlaskの基本的なことは終わったので、以降は「デザイン」を整えながらかっちょいい良いアプリ作成をしていきます。
☟おすすめの参考書はこちらです。
Twitter➡@t_kun_kamakiri
ブログ➡宇宙に入ったカマキリ(物理ブログ)



コメント