2020年11月6日金曜日

RaspberryPi 2B + Apache2 mod-wsgi + Flask Deploy + Form

ログインページを追加する。と言っても、名前を入力するフォームだけ。POST の処理をやってみる。どこかのページにあったものをそのまま使っている。

ただし、デプロイすると動かなくなったのでいろいろ修正している。

ディレクトリ構造は、次のとおり。

|____my_globals.py
|____static/
|____my_app.py
|____templates/
| |____login.html
|____login.py
|____my_app.wsgi

・flask/my_globals.py 未使用。


・flask/my_app.py


login.py の success と login に対して、add_url_rule でパスの設定をしている。
@app.route() を使うよりも、まとめておいた方が分かりやすそうということで、ここに記述している。

from flask import Flask
import sys
import login


app = Flask(__name__)


# @app.route('/hello')
def hello_world():
    msg = 'Hello Flask ' + sys.version
    return msg


if __name__ == '__main__':
    app.add_url_rule('/', 'hello', hello_world)

    # login.py
    app.add_url_rule('/success/<name>', 'success', login.success)
    app.add_url_rule('/login', 'login', login.login, methods=['POST', 'GET'])

    app.run(host='0.0.0.0', port=5000) 

・flask/login.py

login フォームを表示するときに、テンプレート login.html を使用している。

from flask import Flask, redirect, url_for, request, render_template


# @app.route('/success/<name>')
def success(name):
    return 'welcome %s' % name


# @app.route('/login', methods=['POST', 'GET'])
def login():
    if request.method == 'POST':
        user = request.form['nm']
        return redirect(url_for('success', name=user))
    else:
        # http://localhost:5000/login?nm=your_name
        user = request.args.get('nm')
        if user is None:
            return render_template('login.html')
        else:
            return redirect(url_for('success', name=user))

・flask/templates/login.html

<!doctype html>
<html lang="ja">
   <head>
      <meta charset="utf-8">
   </head>
   <body>
      <div>
         <form action="/login" method="post">
            <p>Enter Name:</p>
            <p><input type="text" name="nm" /></p>
            <p><input type="submit" value="submit" /></p>
         </form>
      </div>
   </body>
</html>

・flask/my_app.wsgi

ここで、 app.add_url_rule() をしている。 my_app.py 内では、うまくいかなかった。これで良いのか不明。

import sys

sys.path.insert(0, '/home/pi/flask/')
from my_app import app as application

# add url rules
app = application

import my_app
app.add_url_rule('/', 'hello', my_app.hello_world)

import login
app.add_url_rule('/success/<name>', 'success', login.success)
app.add_url_rule('/login', 'login', login.login, methods=['POST', 'GET'])
勝手に演習
success ページにもテンプレートを使うようにしてみてください。

RaspberryPi 2B + Apache2 mod-wsgi + Flask Deploy

RaspberryPi 2B で、 Flask アプリを Apache2 + wsgi でデプロイする。
将来的に、そのアプリで RaspberryPi のハードウェアを制御する。

 Python 3 用の apache2 mod-wsgi をインストールする。Python 2 用の mod-wsgi が入っていたらアンインストールする。

$ sudo a2dismod wsgi
$ sudo apt remove libapache2-mod-wsgi
$ sudo apt install apache2
$ sudo apt install libapache2-mod-wsgi-py3
$ sudo a2enmod wsgi
$ sudo systemctl restart apache2

Flask app のディレクトリを作成する。
pi@raspberrypi:~ $ mkdir flask
pi@raspberrypi:~ $ cd flask
pi@raspberrypi:~/flask $ mkdir templates
pi@raspberrypi:~/flask $ mkdir static

flask/my_app.py を作成する。
pi@raspberrypi:~/flask $ nano my_app.py
from flask import Flask
import sys


app = Flask(__name__)


@app.route('/')
def hello_world():
    msg = 'Hello Flask ' + sys.version
    return msg


if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000)

flask.conf を作成する。
$ sudo nano /etc/apache2/sites-available/flask.conf
<VirtualHost *:80>
  ServerName 0.0.0.0

  WSGIDaemonProcess my_app user=pi group=pi threads=5
  WSGIScriptAlias / /home/pi/flask/my_app.wsgi

  <Directory /home/pi/flask/>
    WSGIProcessGroup my_app
    WSGIApplicationGroup %{GLOBAL}
    WSGIScriptReloading On

    Require all granted
  </Directory>
</VirtualHost>

wsgi ファイルを作成する。
$ nano ~/flask/my_app.wsgi
import sys

sys.path.insert(0, '/home/pi/flask/')
from my_app import app as application

デフォルトのサイト 000-default を外して、先ほどの flask.conf を有効化する。
$ sudo a2dissite 000-default
$ sudo a2ensite flask
$ sudo systemctl reload apache2

確認。
$ curl http://localhost
Hello Flask 3.7.3 (default, Jul 25 2020, 13:03:44)

他のパソコンなどからも同様に表示される。