こんにちは、吉岡(@yoshiokatsuneo)です。
Pythonは、コードが簡潔、ライブラリが豊富、機械学習で事実上の標準となっていることなどから、現在最も人気があるプログラミング言語の一つと言っても過言ではありません。
「Pythonはアメリカの大学で最も多く教えられている言語である」といった データ もあるくらいです。
PythonのフレームワークにはFlask、Django、Pyramid、Bottle…などがあります。中でもFlaskは「マイクロフレームワーク」と呼ばれるシンプルでわかりやすいフレームワークです。
Flask自体の機能はDjangoのようなフルスタックフレームワークに比べると少ないですが、ORマッパーのSQLAlchemyなど他のライブラリを組み合わせることで、さまざまな用途に利用できます。
ただ、いざ開発でFlaskを使おうとすると、Python、Flask、データベースを動かすための環境構築やデプロイなどが必要になってきます。これが意外と厄介で、手順通りにインストールしたつもりでも、OSやバージョン、ほかのソフトウェアなど、さまざまな原因でエラーが出たりして失敗することもあります。
そこで、今回はブラウザだけでFlaskを使ったWeb開発ができるPaizaCloud Cloud IDEを使い、簡単なToDoリストサービスを作ってみましょう。(2018年10月時点で最新のFlask1.0とデータベースMySQLを使った手順で書いていきます)
PaizaCloudでは、さまざまなフレームワークや言語を使ったWeb開発が、ブラウザだけで簡単に始められます。開発環境がクラウド上で動作しているので、自分でサーバなどを用意しなくても、作ったWebサービスをその場で公開することも可能です!
手順に沿って進めれば、初心者でも10分程度で作れるかと思いますのでぜひ挑戦してみてください。
PaizaCloud Cloud IDEを使う
それでは、始めていきましょう。
PaizaCloud Cloud IDEのサイトはこちらです。
メールアドレスなどを入力して登録すると、登録確認メールが送られてきます。GitHubやGoogle(Gmail)ログインを利用すると、ボタン一つで登録することもできます。
サーバを作る
開発環境となるサーバを作りましょう。
「新規サーバ作成」ボタンを押して、サーバ作成画面を開きます。
データベースを利用できるように、phpMyAdmin, MySQLをクリックして「新規サーバ作成」ボタンを押します。
3秒程度で、Flaskを使える開発環境がブラウザ上にできあがります。
アプリケーション作成
では、Flaskを使ったWebアプリケーションを作成してみましょう。
まず、Flaskのプログラムを書くためのPythonファイルを作ります。
ここでは、"myapp.py"という名前のファイルを作成します。
画面左側の「新規ファイル」アイコンをクリックしてみましょう。
ファイル名を入力する画面がでてくるので、ファイル名を"myapp.py"として、「作成」ボタンを押します。
作成できたら、最初のプログラムを書いてみましょう。
myapp.py:
from flask import Flask app = Flask(__name__) @app.route('/') def index(): return "Hello World!" app.run(debug=True)
書けたら「保存」ボタンを押すか、「Ctrl-S」や「Command-S」キーを押して、ファイルを保存します。
画面左側のファイルファインダを見ると、"myapp.py"というファイルが作られていることがわかります。
10行足らずの短いコードですが、これだけでも立派なWebアプリケーションです!
コードを見ていきましょう。
1行目の"from flask import Flask"では、flaskモジュールを読み込んでいます。
3行目の"app = Flask(name)"では、Flaskアプリケーションを作成しています。
5行目から7行目が、トップページとなるルートパス("/")に対するアクションを指定しています。
Flaskでは"@app.route('/')"のようなデコレータを利用して、URLのパス名("/")とアクション(index関数)の対応づけを行っています。このindex関数の返り値がWebページに表示される内容です。ここでは、"Hello World!"という文字列を返しています。
最後の"app.run()"で、Flaskアプリケーションを実行します。Flaskアプリケーションはデフォルトで5000番ポートで動作します。
また、app.run()の引数に"debug=True"と指定してデバッグモードで実行することで、エラー時にブラウザ上でエラー内容を確認できるようにしておきましょう。
Flaskサーバの起動
それでは、早速このプログラムを動かしてみましょう。
プログラムを動かすには、Pythonのコマンドを使います。
PaizaCloudでは、ブラウザ上で、コマンドを入力するための「ターミナル」を使うことができます。
画面左側の「ターミナル」のボタンをクリックします。
ターミナルが起動しますので、"python3 myapp.py"のように、"python3"のあとに実行するプログラムの名前を入れて、改行キー(エンターキー)を押します。
$ python3 myapp.py
画面の左側に、"5000"と書かれたボタンが追加されました。
Flaskの開発環境では、5000番ポートでサーバが起動します。
PaizaCloudでは、この5000番ポートに対応したブラウザ起動ボタンを自動で追加しています。
ボタンをクリックすると、ブラウザ(PaizaCloudの中で動くブラウザ)が起動して、"Hello World"と表示されました!
なお、FlaskのサーバはHTTPで動作していますが、PaizaCloudではこれをHTTPSに変換しています。またサーバはlocalhostで動作していますが、PaizaCloudでは"https://localhost-サーバ名.paiza-user.cloud:ポート番号"というURLでlocalhostに接続できるようになっています。
サービスを公開して他のユーザやデバイスからもアクセスできるようにする場合、myapp.pyの"app.run(debug=True)"を"app.run(host='0.0.0.0', debug=True)"と変更し、"python3 myapp.py"コマンドを一度終了してから再度実行してサーバを再起動し、外部ネットワークから接続できるようにします。
さらにポート番号を指定せず、 https://ホスト名/ や http://ホスト名/ としてアクセスできるようにする場合、myapp.pyの"app.run(debug=True)"を"app.run(host='0.0.0.0', port=80, debug=True)" と変更してポート番号を80にし、"python3 myapp.py"コマンドを一度終了してから"sudo python3 myapp.py"としてroot権限で実行します。 80番でウェブサーバ(Apache)が起動している場合は"sudo service apache2 stop; sudo systemctl disable apache2”コマンドでウェブサーバを停止します。
また、flaskコマンドを使って"sudo FLASK_APP=myapp.py flask run --host=0.0.0.0 --port=80"のようにして起動することもできます。
HTMLファイルの表示
次は、"Hello World"だけではなくHTMLファイルを作ってみましょう。
まず、HTMLファイルを表示されるため、myapp.pyの中身を以下のように書き換えます。
myapp.py:
from flask import Flask, render_template app = Flask(__name__) @app.route('/') def index(): return render_template('index.html') app.run(debug=True)
コードを見ていきましょう。
1行目で"render_template"を読み込んで利用できるようにし、7行目でそのrender_template関数を実行しています。引数で指定した'index.html'テンプレートファイルを読み込んで、HTMLファイルを生成しています。
なお、FlaskではJinja2というテンプレートエンジンを利用しています。
次に、HTMLファイルを作成しましょう。
まず、画面左側のファイルファインダでホームディレクトリ("/home/ubuntu")を右クリックし、「新規ディレクトリ」を選んで"templates"というディレクトリを作成します。
次に"templates"ディレクトリを右クリックし、「新規ファイル」を選んで"index.html"というファイルを作成します。
templates/index.html:
<h1>Todo List</h1>
それでは、ブラウザ(PaizaCloudの中のブラウザ)をリロードしてみましょう。
HTMLファイルの中身が表示されるはずです!
データベースを作成
次に、データベースを使ってみましょう。
データベースサーバ(MySQL)はサーバ作成時に設定したので起動していますが、設定していない場合は以下のように起動しておきます。
$ sudo systemctl enable mysql $ sudo systemctl start mysql
PaizaCloudでは、このようにroot権限でパッケージをインストールすることもできます。
まずはMySQL上に、このアプリケーションで使うデータベースを作成しましょう。
ここでは、mysqlコマンドを使って、"mydb"というデータベースを作っておきます。
PaizaCloudでは、ブラウザ上でコマンドを入力するための「ターミナル」を使うことができます。
画面左側の「ターミナル」のボタンをクリックします。
以下のコマンドを実行しましょう。
$ mysql -u root create database mydb; exit
データベースが作成できました。
テーブルの作成
続いて、データベース上にテーブルを作成してみましょう。
ターミナル上で、以下のコマンドを実行して"todos"という名前のテーブルを作成します。
$ mysql -u root mydb; use mydb create table todos(id int auto_increment primary key not null, name text); exit
テーブルが作成できました。
phpMyAdminの利用
作成したデータベーステーブルのデータは、phpMyAdminでも確認できます。
PaizaCloudで青いアイコンのPaizaCloudメニューをクリックし、"phpMyAdmin"の"open phpMyAdmin"を選びます。(または、PaizaCloudのブラウザ上で、"http://localhost/phpmyadmin/"と入力します。)
phpMyAdminが表示されました。ここで、データベースの閲覧、編集などができます。データベースの内容を確認しながら開発を進めていくと理解も深まるので、ぜひやってみてください。
ToDoリストの作成
それでは、ToDoリストを作成してみましょう。
まず、"myapp.py"を以下のように編集します。
myapp.py:
from flask import Flask, redirect, render_template, request, url_for import pymysql app = Flask(__name__) conn = pymysql.connect(host='localhost', user='root', password='', db='mydb', autocommit=True, cursorclass=pymysql.cursors.DictCursor ) db = conn.cursor() @app.route('/') def index(): db.execute('SELECT * from todos') todos = db.fetchall() return render_template('index.html', todos = todos) @app.route('/create', methods=('POST',)) def create(): name = request.form['name'] db.execute('INSERT INTO todos(name) VALUES (%s)', (name,)) return redirect(url_for('index')) @app.route('/<int:id>/delete', methods=('POST',)) def delete(id): db.execute('DELETE FROM todos WHERE id = %s', (id,)) return redirect(url_for('index')) app.run(debug=True)
ファイルが編集できたら、「保存」ボタンを押すか、「Ctrl-S」または「Command-S」キーで保存します。
コードを見てみましょう。
1行目では、flaskモジュールから、利用するFlask, redirect, render_template, requestを読み込んでいます。
2行目では、PyMySQLを読み込んでいます。PyMySQLはPythonからMySQLを利用するためのライブラリです。
4行目では"app = Flask(name)"でFlaskのアプリケーションを作成しています。
6行目では、"pymsql.connect()"でPyMySQLのconnect()関数を呼び出し、MySQLと接続しています。
引数では、ホスト名を'hostname'に、ユーザ名を'root'に、パスワードを''(なし)''に、データベース名を'mydb'に指定しています。
"autocommit=True"で、データ追加・変更時に自動的に保存(コミット)するようにします。cursorclassでは、検索結果を辞書として受け取れるようにDictCursorを指定しておきます。
続いて、各URLパスと、その動作(アクション)を設定しましょう。
ToDoリストでは、一覧表示、ToDoの追加、ToDoの削除の3つの操作を行います。
それぞれ、以下のようなURLルーティングを割り当てます。
メソッド | パス名 | 関数名 | 動作 |
---|---|---|---|
GET | / | index | ToDo一覧表示 |
POST | /create | create | ToDo追加 |
POST | /<int:id>/delete | delete | ToDo削除 |
ToDo一覧表示を行うindex関数では、db.execute()でToDo一覧を取得するSQL文'SELECT * from todos'を実行します。
SQLの実行結果は、db.fetchall()関数で取得します。
また、render_template()で"index.html"テンプレートを読み込みます。第二引数に"todos = todos"と指定することで、テンプレート中の"todos"変数で、ToDo一覧を参照できるようにします。
ToDo追加を行うcreate関数では、"request.form['name']"で、テキスト入力フォームから送信された追加ToDoの値を取得して、name変数に保存します。
そして、db.execute()でSQLの"INSERT INTO"文を実行し、todosテーブルに追加します。
PyMySQLでは、SQL文中の"%s"のように指定された場所を第二引数の値(name)で置き換えることができます。このように、直接文字列を生成せずに"%s"を経由することでエスケープ処理を確実に行い、SQLを安全に実行できます。
SQL実行後は、redirect_forでトップページにリダイレクトしています。url_for('index')とurl_forを使うことで、直接URLではなくアクション名で指定できるため、より柔軟なコードになります。
ToDoの削除を行うときは、delete関数を使います。パス名で"/<int:id>/delete"のように指定すれば、deleteの引数でToDoのidを受け取れます。
db.execute()で、SQLの"DELETE FROM"文を使って指定したidのToDoを削除します。
SQL実行後は、redirect_forでトップページにリダイレクトしています。
最後に、"app.run(debug=True)"で作成したFlaskアプリケーションをデバッグモードで実行します。
続いて、HTMLテンプレートファイルを編集しましょう。
テンプレートファイルは複数作成することが多いので、共通のレイアウトファイル(templates/base.html)とToDo表示ページ用ファイル(templates/index.html)に分けて作成していきましょう。
まず、ToDo一覧表示用テンプレートファイル "templates/index.html" を以下のように編集します。
templates/index.html:
{% extends 'base.html' %} {% block content %} <h1>Todo List</h1> {% if error_message %}<p><strong>{{ error_message }}</strong></p>{% endif %} <form action="{{url_for('create')}}" method="post"> <!-- Todo Name --> <div class="form-group"> <label for="name" class="col-sm-3 control-label">Todo</label> <div class="col-sm-6"> <input type="text" name="name" id="name"> </div> </div> <!-- Add Todo Button --> <div class="form-group"> <div class="col-sm-offset-3 col-sm-6"> <button type="submit" class="btn btn-default"> <i class="fa fa-plus"></i> Add Todo </button> </div> </div> </form> <!-- Current Todos --> <h2>Current Todos</h2> <table class="table table-striped todo-table"> <thead> <th>Todos</th><th> </th> </thead> <tbody> {% for todo in todos %} <tr> <!-- Todo Name --> <td> <div>{{ todo['name'] }}</div> </td> <td> <form action="{{url_for('delete', id=todo['id'])}}" method="post"> <button>Delete</button> </form> </td> </tr> {% endfor %} </tbody> </table> {% endblock %}
ファイルが編集できたら「保存」ボタンを押すか、「Ctrl-S」または「Command-S」キーで保存します。
ファイルを見ていきましょう。
ファイルの中に"{% %}"や"{{ }}"と書かれた部分がありますが、これらはPythonのコードとして実行されます。"{% %}"で囲まれた部分のコードは実行だけですが、"{{ }}"では、実行結果がその場所に表示されるようになります。
通常、Pythonではインデントでブロックを作成しますが、HTML中ではインデントが難しいため、"endblock"や"endfor"などでブロックの終わりを示します。
"{% extends 'base.html' %}"では、'base.html'をレイアウトファイルとして利用することを指定します。
"{% block content %}"と"{% endblock %}"で囲んだ範囲がページの中身となる部分で、レイアウトファイルの"content"ブロックに埋め込まれます。
"<form action="{{url_for('create')}}" method="post">"が、追加するToDoの入力フォームになります。送信時は、'create'アクションに対応する'/create'が呼び出されます。
"<input type="text" name="name" id="name">"で、nameという名前のテキスト入力欄を作成します。
"{% for todo in todos %}"では、todos変数でToDo一覧を参照し、一個ずつ"todo"変数に入れて繰り返しています。この中で{{ todo['name'] }}として、ToDoの名前となるnameカラムの値を表示しています。
"<form action="{{url_for('delete', id=todo['id'])}}" method="post">"では、削除ボタン用のフォームを作成しています。url_forを使って、"/delete/ID"というパスを生成しています。
次に、レイアウト用のテンプレートファイル(templates/base.html)を編集しましょう。
"templates"フォルダを右クリックして"新規ファイル"を選択し、"base.html"という名前のファイルを作成します。作成された"templates/base.html"ファイルを以下のように編集します。
templates/base.html:
<!DOCTYPE html> <html> <head> <title>Todo List</title> <!-- CSS And JavaScript --> <link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}"> <link rel="stylesheet" href="//fonts.googleapis.com/css?family=Roboto:300,300italic,700,700italic"> <link rel="stylesheet" href="//cdn.rawgit.com/necolas/normalize.css/master/normalize.css"> <link rel="stylesheet" href="//cdn.rawgit.com/milligram/milligram/master/dist/milligram.min.css"> </head> <body> <div class="container"> {% block content %} {% endblock %} </div> </body> </html>
ファイルが編集できたら「保存」ボタンを押すか、「Ctrl-S」または「Command-S」キーで保存します。
ヘッダ(head)ではHTMLをきれいに表示するため、linkタグでMilligramというCSSフレームワークを読み込んでいます。
"{% block content %}{% endblock %}"が、レイアウトファイルを利用する各ページの内容が埋め込まれる部分になります。
動作確認
プログラミングは以上です。実際に動かしてみましょう。
Flaskアプリケーション(サーバ)を終了している場合は、以下のように実行します。
$ python3 myapp.py
ブラウザアイコン(5000)をクリックして、PaizaCloud内のブラウザを起動します。
最初はToDoはありませんが、"Todo List"ページが表示されていますよね。
ToDoの追加や削除をしてみましょう。
動きましたね!FlaskとMySQLで作ったToDoリストの完成です!
なお、PaizaCloudの無料プランでは、一定時間が経つとサーバは停止します。継続的に動かしたい場合は、ベーシックプランへアップデートしてください。
詳しくはこちら
まとめ
というわけで、PaizaCloudを使って、開発環境などを構築することなく、ブラウザだけでFlaskとMySQLを使ったWebアプリケーションを作ってみました。
すぐに作れるので、みなさんもぜひ試してみてください!
(何かサービスができたらpaiza( @paiza_official )まで教えてくれるとうれしいです!)
「PaizaCloud」は、環境構築に悩まされることなく、ブラウザだけで簡単にウェブサービスやサーバアプリケーションの開発や公開ができます。
「paizaラーニング」では、未経験者でもブラウザさえあれば、今すぐプログラミングの基礎が動画で学べるレッスンを多数公開しております。
そして、paizaでは、Webサービス開発企業などで求められるコーディング力や、テストケースを想定する力などが問われるプログラミングスキルチェック問題も提供しています。
スキルチェックに挑戦した人は、その結果によってS・A・B・C・D・Eの6段階のランクを取得できます。必要なスキルランクを取得すれば、書類選考なしで企業の求人に応募することも可能です。「自分のプログラミングスキルを客観的に知りたい」「スキルを使って転職したい」という方は、ぜひチャレンジしてみてください。