#簡易ログイン機能+多言語JSONのDBを作る
新年あけましておめでとうございます。この記事では、旧年の成果を発表いたしたいと思います。筆者のTwitter: yosiyos38795255 GitHub: @yosiyoshi です。よろしくお願いいたします。
##(1)必要な環境
まず、Python3の開発環境(筆者の場合はAnaconda3+Spyder)が必要。
次にpipでWebフレームワークのFlaskをインストール:
pip install Flask
あとはcurlなどがインストールされているならば、それを利用すること。
##(2)目標
RESTfulなJSONデータベースを利用して簡単なログインシステムと、その認証後に開始されるデータベースのバックエンドコードを実装すること。ただし、実はデータベース本体にログイン機能は付属しないので、ログインを通さずに操作できます(要するにログインもどき)。
##(3)実装
https://github.com/yosiyoshi/flask_practice
まず、ログイン機能の実装は以下のライブラリを使用します。
from flask import Flask, render_template, jsonify, request
import json
import re
import subprocess
import webbrowser
ユーザデータはcurlによりJSON形式で予め登録されるものとします。
まず、JSON-APIのI/Oを司るバックエンドコードをlogin.pyとして、まずその基礎部分を以下のように作成します:
app = Flask(__name__)
data = []
@app.route('/')
def form():
return render_template('login.html')
@app.route('/data', methods=['POST'])
def add_data():
data.append(request.get_json())
return '', 204
#ここにログイン処理を書く
if __name__ == "__main__":
app.run(host='localhost', debug=True)
@app.route('/')とは、
$ python login.py
実行時にアクセスできるローカルアドレス"localhost(:5000)"で行なわれる処理の定義を宣言するものです。次の行にある、def form():
以降のrender_template('login.html')
が、実行されるlogin.pyのディレクトリ直下に存在する"templates/login.html"を呼び出し、これをテンプレートとして読み込むのです。
@app.route('/data', methods=['POST'])とは、"localhost:5000/data"へのJSONデータの書き込みを許可するもので、コード実行中に当該アドレスへのcurl使用が可能です。
curl -i -H "Content-Type: application/json" -d "{\"id\":\"a\",\"password\": \"a\"}" http://localhost:5000/data
例えば、以上のコードを実行すると、"localhost:5000/data"に存在するデータベースへ、
{"id":"a","password": "a"}
というJSONデータが書き込まれます。ただし後述するログイン処理を考慮に入れると、ログインするのに必要なJSONデータは一つ(つまり一人分のidとpasswordの組合せ)だけです。なお、当該アドレス"localhost:5000/data"へのブラウザによるアクセスは許可されません。したがって、外部からのデータ読み込みはできません。
次に、ログイン処理を書きます:
@app.route('/auth', methods = ['POST', 'GET'])
def result():
if request.method == 'POST':
getkey = request.form['key']
getvalue = request.form['value']
authkey = "id:"+getkey+",password:"+getvalue
jsdump = json.dumps(data)
key = re.sub(r'["{[/ \]}"]', "", jsdump)
if key == authkey:
auth_res = "Login successful"
#ログイン後にサブプロセスを起動したいので、後にここへ追記
else:
auth_res = "Login failed"
return "Result: {}".format(auth_res)
このgetkeyとgetvalueで、idとpasswordのテキストフォームに入力された文字列を呼び出し、authkeyという新しい文字列に結合します。jsdumpでは、先ほど入力された
{"id":"a","password": "a"}
のようなJSONデータをstringデータに変換し、
keyで{}や[]のようなJSONデータ内に元々含まれていた記号を、re.sub(文字列,"")の命令により空文字へ置き換え、削除します。
そして、key(登録されていたJSONのidとパスワード) == authkey(入力されたidとパスワード)が一致した場合にauth_res(ログイン結果)として"Login successful"、あるいはそうでなければ"Login failed"を返します。
ここまでのコード: https://github.com/yosiyoshi/flask_practice/blob/master/login.py
/templates
ディレクトリにlogin.htmlを作成:
<html>
<body>
<form action = "/auth" method = "POST">
<p>Name /ID: <input type = "text" name = "key" /></p>
<p>Password: <input type ="text" name = "value" /></p>
<p><input type = "submit" value = "submit" /></p>
</form>
</body>
</html>
ここまでのコード: https://github.com/yosiyoshi/flask_practice/blob/master/templates/login.html
さて、ログインが成功したのちの処理を"lang_json.py"として次のように記述:
from flask import Flask, jsonify, request
from ynltk import Langvowel
from collections import Counter
import json
app = Flask(__name__)
l = Langvowel()
data = []
@app.route('/')
def info():
return "'/data' to show the content; '/lang' to detect in what language written; '/len' to measure the length."
@app.route('/auth')
def message():
return "Login successful: please visit http://localhost:5000/ again."
@app.route('/data')
def get_data():
return jsonify(data)
@app.route('/lang')
def detec_lang():
return l.langvowel(str(data))
@app.route('/len')
def json_len():
return str(len(json.dumps(data)))
@app.route('/data', methods=['POST'])
def add_data():
data.append(request.get_json())
return '', 204
if __name__ == '__main__':
app.run(host='localhost',debug=True)
print("Index information is here -> http://localhost:5000/")
ynltkは私がhttps://github.com/yosiyoshi/IntelligenTXT/blob/master/ynltk.py
にて公開している自然言語処理のライブラリで、今回は言語判定に利用します。
まずこのコードを実行すると、curlを通じてJSONデータのI/Oと"localhost:5000/data"のデータへアクセスすることができます。
そして、"/data"では登録されたデータを一覧にしてみることができます。
"/len"ではJSONデータの「長さ(文字数?)」が計算され、返されます。
"/lang"では入力されたJSONデータの言語が判別され、返されます。
ここまでのコード: https://github.com/yosiyoshi/flask_practice/blob/master/lang_json.py
先にlogin.py(簡易ログイン)
とlang_json.py(JSONデータベース)
という二つのコードを独立して書きましたが、ここから先は二つの機能を連携させる必要があります。つまり、ログイン→データベース操作というフローを完成させるのです。
そのため、login.py
を小改造し、log2json.py
に書き換えます:
#@app.route('/auth', methods = ['POST', 'GET'])
#def result():
# if request.method == 'POST':
# getkey = request.form['key']
# getvalue = request.form['value']
# authkey = "id:"+getkey+",password:"+getvalue
# jsdump = json.dumps(data)
# key = re.sub(r'["{[/ \]}"]', "", jsdump)
# if key == authkey:
# auth_res = "Login successful"
subprocess.call(['python', 'lang_json.py'])
url = "http://localhost:5000/"
webbrowser.open(url)
# else:
# auth_res = "Login failed"
# return "Result: {}".format(auth_res)
コメントアウトされていない部分のコードを、"localhost:5000/auth"の挙動に追加することで、"Login successful"が表示される前に、先述の'lang_json.py'が起動します。
この時ログインが成功すると、
こうなれば成功です。
ここまでのコード: https://github.com/yosiyoshi/flask_practice/blob/master/log2json.py
##(3)まとめ
まずログインすると、データベースに誘導されます。
データベースはRESTfulスタイルで、外部から編集できます。
##(4)最後に
駄文長文失礼しました。もともとこれらのコードは独立しており、Flaskの演習として弄っていました。従って注意が及ばず、言葉足らずや知識不足の部分も残っていると思います。ご指摘やご教授は歓迎いたします。ご閲覧ありがとうございました。