Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
1
Bottleではじめる
WEBアプリの最初の一歩
2016/07/06
みんなのPython勉強会#14
山田 聡(@denzowill)
2
# whoami
•名前
• 山田 聡(@denzowill)
•仕事
• DBエンジニア(○racle,PostgreSQL)
• チョットだけWebLogicエンジニア
• Pythonは趣味
•スキル
• 統計もわかりません
• 機械...
3
アジェンダ
•WEBアプリ?
•フレームワークとハードル
•だからBottle
4
アジェンダ
•WEBアプリ?
•フレームワークとハードル
•だからBottle
5
WEBアプリ?
•そもとも普通のWEBサーバ
Apacheとか、WEBサーバは指定されたアドレスにある
静的なHTMLをそのまま戻す。内容は固定。
6
WEBアプリ?
•昔からのWEBアプリケーション
サーバでJavaとかPythonが動いてて、HTTP通信で
渡ってきたデータを元に、頑張って動的なHTMLを
組み立てて、ブラウザでそれを表示する。
7
WEBアプリ?
•最近のWEBアプリケーション
動的なHTMLを受けとるだけでなく、Javascriptが頑
張って裏ですっごい非同期通信して、ページ遷移無しで
もいろいろ画面がかわる
8
今回は?
9
今回は?
今回はこちら中心です。
(基本なので。)
10
WEBアプリに必要なもの
ルーティング
http://xx/list
http://xx/add
http://xx/del/2
入口
view_list()
add_item()
del_item(
id=2
)
→ URLと処理のマッ...
11
WEBアプリに必要なもの
ビジネスロジック → あなたがやりたいこと
普通の処理
def view_list():
connect = db.connect()
cur = connect.cursor()
cur.execute("se...
12
WEBアプリに必要なもの
HTMLの表示 → ビジネスロジックの結果を画面に
<h1>アイテム一覧</h1>
<table border="1">
%for item in item_list:
<tr>
<td>{{item.id}}<...
13
アジェンダ
•WEBアプリ?
•フレームワークとハードル
•だからBottle
14
フレームワークとハードル
•WEBアプリケーションフレームワーク(WAF)?
あるルールに従って作成すると、簡単にWEBアプリケー
ションが作成できるようにしたライブラリの集合のよう
なもの。
15
フレームワークのよくある機能
•ルーティング
• URLに応じて処理先を割り当て
•テンプレート
• HTMLを簡単に動的に組み立て
•ORM
• RDBMS等をオブジェクトとして透過的に操作
16
フレームワークのよくある機能
•ルーティング
• URLに応じて処理先を割り当て
•テンプレート
• HTMLを簡単に動的に組み立て
•ORM
• RDBMS等をオブジェクトとして透過的に操作
フレームワークによっては
他のORMライブラ...
17
WEBアプリのデザインパターン
MODEL
VIEW
CONTROLER
ビジネスロジック
DBでの永続化
画面表示
HTML/CSS
ルーティング
MVの橋渡し
18
WEBアプリのデザインパターン
MODEL
VIEW
CONTROLER
19
WEBアプリのデザインパターン
MODEL
VIEW
CONTROLER
→ こうするとキレイに書けるよって話
20
このあたりから
途端に辛い
21
なんでつらい?
•MVCとかMTVとかいろいろある
•フレームワーク毎に解釈が違ったりする
•フレームワークの作法に従えばなんとなくは
できる
•でも、それはそのフレームワークに縛られる
22
なんでつらい?
•MVCとかMTVとかいろいろある
•フレームワーク毎に解釈が違ったりする
•フレームワークの作法に従えばなんとなくは
できる
•でも、それはそのフレームワークに縛られる
一旦MVCは忘れて
基本を見てみる
23
機能と学習量の関係
すごい
つらい
24
機能と挫折率の関係
すごい
つらい
25
機能と挫折率の関係
すごい
つらい
26
アジェンダ
•WEBアプリ?
•フレームワークとハードル
•だからBottle
27
Bottleはとてもシンプル
28
Bottleはとてもシンプル
•テンプレート、ルーティングの機能あり(ORM無し)
•bottle.pyという1ファイルがすべて
•外部ライブラリに依存性無し
•シンプルだからWEBアプリの動きをつかみやすい
学習に最適!
29
この時点で残り10分
ですが(想定)、いまから
アプリ書きます
30
つくるもの
•アイテムの一覧が見られる(参照)
•フォームからアイテムを追加できる(登録)
•既存のアイテムを削除できる(更新)
この3つが大体基本
31
Bottleセットアップ
$ mkdir <適当なディレクトリ>
$ cd <作ったディレクトリ>
$ wget https://github.com/bottlepy/bottle/raw/master/bottle.py
bottle...
32
Bottleの動作確認
from bottle import route, run
# / にアクセスしたら index関数が呼ばれる
@route("/")
def index():
# 画面に表示されて欲しいHTMLを戻す
retur...
33
$ python app.py
34
アイテム一覧見たい
# アイテム一覧を戻す関数
@route("/list")
def view_list():
# ダミーデータ(あとでDBから取得するようにする)
item_list = [
{"id": 1, "name": "りん...
35
http://127.0.0.1:9999/list
36
HTMLをベタがき
つらいので
テンプレートつかう
37
テンプレート使う
<h1>アイテム一覧</h1>
<table border="1">
%for item in item_list:
<tr>
<td>{{item["id"]}}</td>
<td>{{item["name"]}}</...
38
テンプレート使う
from bottle import route, run, template
:
:
# アイテム一覧を戻す関数
@route("/list")
def view_list():
# ダミーデータ(あとでDBから取得す...
39
http://127.0.0.1:9999/list
さっきと同じだけど\(^o^)/
40
DBのデータを参照する
(sqliteつかう)
41
初期データの準備
import sqlite3
# items.dbとつなぐ(なければ作られる)
conn = sqlite3.connect('items.db')
c = conn.cursor()
# テーブル作成
c.execut...
42
DBからitem_listを取得するように変更
import sqlite3
from bottle import route, run, template
:
:
@route("/list")
def view_list():
# i...
43
登録処理作る
44
登録用のフォームのテンプレート作る
<h1>アイテム登録</h1>
<form action='' method='POST'>
<input type='text' name='item_name' placeholder='アイテム名...
45
ルーティングとメソッド作成
@route("/add", method=["GET","POST"])
def add_item():
return template("add_tmpl")
app.py GETとPOST
両方でアクセス...
46
http://127.0.0.1:9999/add
登録は押せる
ただし何も起きない
47
ルーティングとメソッド作成
@route("/add", method=["GET","POST"])
def add_item():
if request.method == "POST":
# POSTアクセスならDBに登録する
# ...
48
http://127.0.0.1:9999/add
49
削除処理作る
50
一覧画面のテンプレート変更し削除リンク追加
<h1>アイテム一覧</h1>
<a href='/add' >新規作成</a>
<table border="1">
%for item in item_list:
<tr>
<td>{{it...
51
削除処理を追加、URLから削除対象のID取得
# /del/100 -> item_id = 100
# /del/one -> HTTPError 404
@route("/del/<item_id:int>")
def del_ite...
52
http://127.0.0.1:9999/list
押したら消える
53
完成https://github.com/denzow/sample_bottle
54
10分で基本的な要素を
抑えたWEBアプリが
できました(想定では)
55
次の一歩に向けて
•参照・登録・削除ができればアプリは作れる
•見た目はCSSやJavascriptを覚える
• 参考:Bootstrap http://getbootstrap.com/
•アプリが大きくなると各所で辛さが出る
• SQ...
56
ご清聴ありがとうございました。
Upcoming SlideShare
Loading in …5
×

bottleで始めるWEBアプリの最初の一歩

(2017/09 追記)http://www.denzow.me/archive/category/Bottle でまとめ直し始めました
PythonのWAFの中でもとりわけ軽量・シンプルなBottleを使って
アプリケーション作成の第一歩を踏み出すお手伝いをします。

  • Login to see the comments

bottleで始めるWEBアプリの最初の一歩

  1. 1. 1 Bottleではじめる WEBアプリの最初の一歩 2016/07/06 みんなのPython勉強会#14 山田 聡(@denzowill)
  2. 2. 2 # whoami •名前 • 山田 聡(@denzowill) •仕事 • DBエンジニア(○racle,PostgreSQL) • チョットだけWebLogicエンジニア • Pythonは趣味 •スキル • 統計もわかりません • 機械学習もわかりません • ちょっとWEBアプリわかります
  3. 3. 3 アジェンダ •WEBアプリ? •フレームワークとハードル •だからBottle
  4. 4. 4 アジェンダ •WEBアプリ? •フレームワークとハードル •だからBottle
  5. 5. 5 WEBアプリ? •そもとも普通のWEBサーバ Apacheとか、WEBサーバは指定されたアドレスにある 静的なHTMLをそのまま戻す。内容は固定。
  6. 6. 6 WEBアプリ? •昔からのWEBアプリケーション サーバでJavaとかPythonが動いてて、HTTP通信で 渡ってきたデータを元に、頑張って動的なHTMLを 組み立てて、ブラウザでそれを表示する。
  7. 7. 7 WEBアプリ? •最近のWEBアプリケーション 動的なHTMLを受けとるだけでなく、Javascriptが頑 張って裏ですっごい非同期通信して、ページ遷移無しで もいろいろ画面がかわる
  8. 8. 8 今回は?
  9. 9. 9 今回は? 今回はこちら中心です。 (基本なので。)
  10. 10. 10 WEBアプリに必要なもの ルーティング http://xx/list http://xx/add http://xx/del/2 入口 view_list() add_item() del_item( id=2 ) → URLと処理のマッピング
  11. 11. 11 WEBアプリに必要なもの ビジネスロジック → あなたがやりたいこと 普通の処理 def view_list(): connect = db.connect() cur = connect.cursor() cur.execute("select id,name from items order by id") item_list = [] for row in cur.fetchall(): item_list.append({ "id":row[0], "item_name": row[1] }) return item_list DBから商品一覧を 取得したい etc
  12. 12. 12 WEBアプリに必要なもの HTMLの表示 → ビジネスロジックの結果を画面に <h1>アイテム一覧</h1> <table border="1"> %for item in item_list: <tr> <td>{{item.id}}</td> <td>{{item.name}}</td> </tr> %end </table>
  13. 13. 13 アジェンダ •WEBアプリ? •フレームワークとハードル •だからBottle
  14. 14. 14 フレームワークとハードル •WEBアプリケーションフレームワーク(WAF)? あるルールに従って作成すると、簡単にWEBアプリケー ションが作成できるようにしたライブラリの集合のよう なもの。
  15. 15. 15 フレームワークのよくある機能 •ルーティング • URLに応じて処理先を割り当て •テンプレート • HTMLを簡単に動的に組み立て •ORM • RDBMS等をオブジェクトとして透過的に操作
  16. 16. 16 フレームワークのよくある機能 •ルーティング • URLに応じて処理先を割り当て •テンプレート • HTMLを簡単に動的に組み立て •ORM • RDBMS等をオブジェクトとして透過的に操作 フレームワークによっては 他のORMライブラリを 組み込むケースも
  17. 17. 17 WEBアプリのデザインパターン MODEL VIEW CONTROLER ビジネスロジック DBでの永続化 画面表示 HTML/CSS ルーティング MVの橋渡し
  18. 18. 18 WEBアプリのデザインパターン MODEL VIEW CONTROLER
  19. 19. 19 WEBアプリのデザインパターン MODEL VIEW CONTROLER → こうするとキレイに書けるよって話
  20. 20. 20 このあたりから 途端に辛い
  21. 21. 21 なんでつらい? •MVCとかMTVとかいろいろある •フレームワーク毎に解釈が違ったりする •フレームワークの作法に従えばなんとなくは できる •でも、それはそのフレームワークに縛られる
  22. 22. 22 なんでつらい? •MVCとかMTVとかいろいろある •フレームワーク毎に解釈が違ったりする •フレームワークの作法に従えばなんとなくは できる •でも、それはそのフレームワークに縛られる 一旦MVCは忘れて 基本を見てみる
  23. 23. 23 機能と学習量の関係 すごい つらい
  24. 24. 24 機能と挫折率の関係 すごい つらい
  25. 25. 25 機能と挫折率の関係 すごい つらい
  26. 26. 26 アジェンダ •WEBアプリ? •フレームワークとハードル •だからBottle
  27. 27. 27 Bottleはとてもシンプル
  28. 28. 28 Bottleはとてもシンプル •テンプレート、ルーティングの機能あり(ORM無し) •bottle.pyという1ファイルがすべて •外部ライブラリに依存性無し •シンプルだからWEBアプリの動きをつかみやすい 学習に最適!
  29. 29. 29 この時点で残り10分 ですが(想定)、いまから アプリ書きます
  30. 30. 30 つくるもの •アイテムの一覧が見られる(参照) •フォームからアイテムを追加できる(登録) •既存のアイテムを削除できる(更新) この3つが大体基本
  31. 31. 31 Bottleセットアップ $ mkdir <適当なディレクトリ> $ cd <作ったディレクトリ> $ wget https://github.com/bottlepy/bottle/raw/master/bottle.py bottle.pyを持ってくれば終わり
  32. 32. 32 Bottleの動作確認 from bottle import route, run # / にアクセスしたら index関数が呼ばれる @route("/") def index(): # 画面に表示されて欲しいHTMLを戻す return "<h1>WELCOME STAPY!</h1>" # サーバを起動(localhost:9999で起動する設定) run(reloader=True, port=9999) app.py
  33. 33. 33 $ python app.py
  34. 34. 34 アイテム一覧見たい # アイテム一覧を戻す関数 @route("/list") def view_list(): # ダミーデータ(あとでDBから取得するようにする) item_list = [ {"id": 1, "name": "りんご"}, {"id": 2, "name": "ばなな"}, {"id": 3, "name": "すいか"}, ] # 表示用のHTMLを組み立てる display_html = "<table border='1'>" for item in item_list: display_html += "<tr>" display_html += "<td>{}</td>".format(item["id"]) display_html += "<td>{}</td>".format(item["name"]) display_html += "</tr>" display_html += "</table>" return display_html app.py
  35. 35. 35 http://127.0.0.1:9999/list
  36. 36. 36 HTMLをベタがき つらいので テンプレートつかう
  37. 37. 37 テンプレート使う <h1>アイテム一覧</h1> <table border="1"> %for item in item_list: <tr> <td>{{item["id"]}}</td> <td>{{item["name"]}}</td> </tr> %end </table> list_tmpl.tpl ほぼHTML % や{{ }}のなかだけ Pythonのように処理される item_listは 使うときにapp.pyから ディクショナリを渡す
  38. 38. 38 テンプレート使う from bottle import route, run, template : : # アイテム一覧を戻す関数 @route("/list") def view_list(): # ダミーデータ(あとでDBから取得するようにする) item_list = [ {"id": 1, "name": "りんご"}, {"id": 2, "name": "ばなな"}, {"id": 3, "name": "すいか"}, ] # 表示はテンプレートを戻すだけ return template("list_tmpl", item_list=item_list) app.py
  39. 39. 39 http://127.0.0.1:9999/list さっきと同じだけど\(^o^)/
  40. 40. 40 DBのデータを参照する (sqliteつかう)
  41. 41. 41 初期データの準備 import sqlite3 # items.dbとつなぐ(なければ作られる) conn = sqlite3.connect('items.db') c = conn.cursor() # テーブル作成 c.execute("create table items(id, name)") # 3行投入 c.execute("insert into items values(1,'りんご')") c.execute("insert into items values(2,'ばなな')") c.execute("insert into items values(3,'すいか')") # 確定 conn.commit() # バイバイ conn.close() pythonを対話型で起動して実行
  42. 42. 42 DBからitem_listを取得するように変更 import sqlite3 from bottle import route, run, template : : @route("/list") def view_list(): # items.dbとつなぐ conn = sqlite3.connect('items.db') c = conn.cursor() c.execute("select id,name from items order by id") item_list = [] for row in c.fetchall(): item_list.append({ "id": row[0], "name": row[1] }) conn.close() # 表示はテンプレートを戻すだけ return template("list_tmpl", item_list=item_list) app.py
  43. 43. 43 登録処理作る
  44. 44. 44 登録用のフォームのテンプレート作る <h1>アイテム登録</h1> <form action='' method='POST'> <input type='text' name='item_name' placeholder='アイテム名'/> <input type='submit' value='登録' /> </form> add_tmpl.tpl
  45. 45. 45 ルーティングとメソッド作成 @route("/add", method=["GET","POST"]) def add_item(): return template("add_tmpl") app.py GETとPOST 両方でアクセス できるようにする
  46. 46. 46 http://127.0.0.1:9999/add 登録は押せる ただし何も起きない
  47. 47. 47 ルーティングとメソッド作成 @route("/add", method=["GET","POST"]) def add_item(): if request.method == "POST": # POSTアクセスならDBに登録する # フォームから入力されたアイテム名の取得(Python2ならrequest.POST.getunicodeを使う) item_name = request.POST.getunicode("item_name") conn = sqlite3.connect('items.db') c = conn.cursor() # 現在の最大ID取得(fetchoneの戻り値はタプル) new_id = c.execute("select max(id) + 1 from items").fetchone()[0] c.execute("insert into items values(?,?)", (new_id, item_name)) conn.commit() conn.close() return "SUCCESS" else: # GETアクセスならフォーム表示 return template("add_tmpl") app.py POST/GETで分岐 GETはフォーム出すだけ formからPOSTされた データを取得
  48. 48. 48 http://127.0.0.1:9999/add
  49. 49. 49 削除処理作る
  50. 50. 50 一覧画面のテンプレート変更し削除リンク追加 <h1>アイテム一覧</h1> <a href='/add' >新規作成</a> <table border="1"> %for item in item_list: <tr> <td>{{item["id"]}}</td> <td>{{item["name"]}}</td> <td><a href="/del/{{item['id']}}">削除</a></td> </tr> %end </table> list_tmpl.tpl ついでに新規作成つけとく 削除リンク /del/1や/del/2といった URLへリンクする
  51. 51. 51 削除処理を追加、URLから削除対象のID取得 # /del/100 -> item_id = 100 # /del/one -> HTTPError 404 @route("/del/<item_id:int>") def del_item(item_id): conn = sqlite3.connect('items.db') c = conn.cursor() # 指定されたitem_idを元にDBデータを削除 c.execute("delete from items where id=?", (item_id,)) conn.commit() conn.close() # 処理終了後に一覧画面に戻す return redirect("/list") app.py delの後ろに数字がくると 関数の引数として取れる 後はそれで delete文するだけ
  52. 52. 52 http://127.0.0.1:9999/list 押したら消える
  53. 53. 53 完成https://github.com/denzow/sample_bottle
  54. 54. 54 10分で基本的な要素を 抑えたWEBアプリが できました(想定では)
  55. 55. 55 次の一歩に向けて •参照・登録・削除ができればアプリは作れる •見た目はCSSやJavascriptを覚える • 参考:Bootstrap http://getbootstrap.com/ •アプリが大きくなると各所で辛さが出る • SQLの管理 • ルーティングの管理 •辛くなったらもっと高機能なWAFを覚えて見る
  56. 56. 56 ご清聴ありがとうございました。

×