小学6年生の長男が夏休みの自由研究にPythonを勉強したいというので付き合ってみました。
どこから手を付けていけばわからないので、いくつか課題を出し、それを実現するコードを一緒に書くということを繰り返しました。
この記事では、「課題8 掲示板」について扱います。その他の課題については下記の記事をご覧ください。
- 夏休みなので小学生とPythonを勉強してみた - 課題1 FizzBuzz - Qiita
- 夏休みなので小学生とPythonを勉強してみた - 課題2 掛け算九九 - Qiita
- 夏休みなので小学生とPythonを勉強してみた - 課題3 掛け算ゲーム - Qiita
- 夏休みなので小学生とPythonを勉強してみた - 課題4 じゃんけん - Qiita
- 夏休みなので小学生とPythonを勉強してみた - 課題5 サイコロの目の出る確率 - Qiita
- 夏休みなので小学生とPythonを勉強してみた - 課題6 写真の整理 - Qiita
- 夏休みなので小学生とPythonを勉強してみた - 課題7 掛け算ゲームWeb版 - Qiita
- 夏休みなので小学生とPythonを勉強してみた - 課題9 顔の検出 - Qiita
- 夏休みなので小学生とPythonを勉強してみた - 課題10 顔の認識 - Qiita
コードはGitHubにて公開しています。
課題8-1 入力フォームを表示する
指示
ユーザーが入力するフォームを表示するプログラムを作りましょう。
ヒント
Webアプリケーションの見栄えをよくするためにBootstrapを使うことにします。
ドキュメントのQuick startを参考にして作成します。
回答例
01_form.py
from flask import Flask
from flask import render_template
app = Flask(__name__)
@app.route('/', methods=['GET'])
def get():
return render_template('01.html')
templates/01.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Sample BBS</title>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<div class="container">
<h1 class="navbar-brand">Sample BBS</h1>
</div>
</nav>
<div class="container">
<form method="post">
<textarea class="form-control" name="message"></textarea>
<div class="d-flex justify-content-end"><button class="btn btn-primary" type="submit">Post</button></div>
</form>
</div>
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
</body>
</html>
実行例
$ FLASK_APP=01_form.py FLASK_ENV=development flask run --host=0.0.0.0
* Serving Flask app "01_form.py" (lazy loading)
* Environment: development
* Debug mode: on
* Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
* Restarting with stat
* Debugger is active!
* Debugger PIN: 867-383-452
127.0.0.1 - - [23/Aug/2019 07:03:23] "GET / HTTP/1.1" 200 -
課題8-2 リダイレクト
指示
フォームに入力されたら、rootにリダイレクトされるプログラムを作りましょう。
ヒント
FlaskのQuickstartにある、Redirects and Errorsの節を参考にして作成します。
回答例
templates/02_redirect.py
from flask import Flask
from flask import redirect
from flask import render_template
app = Flask(__name__)
@app.route('/', methods=['GET'])
def get():
return render_template('02.html')
@app.route('/', methods=['POST'])
def post():
return redirect('/', 303)
実行例
$ FLASK_APP=02_redirect.py FLASK_ENV=development flask run --host=0.0.0.0
* Serving Flask app "02_redirect.py" (lazy loading)
* Environment: development
* Debug mode: on
* Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
* Restarting with stat
* Debugger is active!
* Debugger PIN: 867-383-452
127.0.0.1 - - [23/Aug/2019 07:12:10] "GET / HTTP/1.1" 200 -
127.0.0.1 - - [23/Aug/2019 07:12:12] "POST / HTTP/1.1" 303 -
127.0.0.1 - - [23/Aug/2019 07:12:12] "GET / HTTP/1.1" 200 -
課題8-3 投稿処理
指示
フォームに入力された内容を表示するプログラムを作りましょう。
ヒント
Flaskで使用しているレンダリング・エンジンはJinja2です。Jinja2のドキュメントにforループなどの書き方が載っています。
回答例
03_post.py
from flask import Flask
from flask import redirect
from flask import render_template
from flask import request
app = Flask(__name__)
posts = []
@app.route('/', methods=['GET'])
def get():
return render_template('03.html', posts=posts)
@app.route('/', methods=['POST'])
def post():
posts.insert(0, {'message': request.form['message']})
return redirect('/', 303)
templates/03.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Sample BBS</title>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<div class="container">
<h1 class="navbar-brand">Sample BBS</h1>
</div>
</nav>
<div class="container">
<form method="post">
<textarea class="form-control" name="message"></textarea>
<div class="d-flex justify-content-end"><button class="btn btn-primary" type="submit">Post</button></div>
</form>
<br>
<div class="list-group">
{% for post in posts %}
<div class="list-group-item">
<p class="list-group-item-text">{{ post['message'] }}</p>
</div>
{% endfor %}
</div>
</div>
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
</body>
</html>
実行例
$ FLASK_APP=03_post.py FLASK_ENV=development flask run --host=0.0.0.0
* Serving Flask app "03_post.py" (lazy loading)
* Environment: development
* Debug mode: on
* Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
* Restarting with stat
* Debugger is active!
* Debugger PIN: 867-383-452
127.0.0.1 - - [23/Aug/2019 07:17:47] "GET / HTTP/1.1" 200 -
127.0.0.1 - - [23/Aug/2019 07:18:06] "POST / HTTP/1.1" 303 -
127.0.0.1 - - [23/Aug/2019 07:18:06] "GET / HTTP/1.1" 200 -