125
138

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

flaskで簡単なwebアプリ作成

Last updated at Posted at 2016-05-14

やるサイト

virtualenvでflask用の環境用意

virtualenvのインストールと使い方はここ参照。

$ mkvirtualenv flaski
$ workon flaski

インストール

(flaski):flask_test hoge$ pip install flask
(flaski):flask_test hoge$ pip install sqlalchemy

ローカルでwebサーバー立てて、ブラウザにHello Worldを表示。

{app.py}
from flask import Flask
app = Flask(__name__)

# http://127.0.0.1:5000をルートとして、("")の中でアクセスポイント指定
# @app.route("hoge")などで指定すると、http://127.0.0.1:5000/hogeでの動作を記述できる。
@app.route("/")
def hello():
    return "Hello World!"

if __name__ == "__main__":
    # webサーバー立ち上げ
    app.run()

を作り、python app.pyで実行すると、以下が標準出力に表示される。

(flaski)hoge:src hoge$ python app.py 
 * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)

ブラウザでhttp://127.0.0.1:5000/を打ち込むと以下が表示される。

スクリーンショット 2016-05-10 21.35.04.png

SQLAlchemyを用いたSQLiteの操作

ファイル構成

├── flaski
│   ├── __init__.py
│   ├── database.py
│   └── models.py
├── do_create.py
└── do_insert.py

各スクリプトと動作確認

{database.py}
# -*- coding: utf-8 -*-

from sqlalchemy import create_engine
from sqlalchemy.orm import scoped_session, sessionmaker
from sqlalchemy.ext.declarative import declarative_base
import os

# wiki.dbという名前のdbファイルの作成を指定
databese_file = os.path.join(os.path.abspath(os.path.dirname(__file__)), 'wiki.db')
# sqlliteを指定して、テーブルのcreateを指定。
engine = create_engine('sqlite:///' + databese_file, convert_unicode=True)
# bindにテーブルcreateを指定。
db_session = scoped_session(sessionmaker(autocommit=False,
                                         autoflush=False,
                                         bind=engine))
# declarative_baseのインスタンス生成。
Base = declarative_base()
# 実行用のセッション格納?
Base.query = db_session.query_property()


def init_db():
    import flaski.models
    # Baseの内容でcreate実行?
    Base.metadata.create_all(bind=engine)
{models.py}
# -*- coding: utf-8 -*-

from sqlalchemy import Column, Integer, String, Text, DateTime
from flaski.database import Base
from datetime import datetime


class WikiContent(Base):
    __tablename__ = 'wikicontents'                  # テーブル名
    id = Column(Integer, primary_key=True)          # カラム1(id)
    title = Column(String(128), unique=True)        # カラム2(title)
    body = Column(Text)                             # カラム3(body)
    date = Column(DateTime, default=datetime.now()) # カラム4(date) デフォルト現在日時を設定

    def __init__(self, title=None, body=None, date=None):
        self.title = title
        self.body = body
        self.date = date

    def __repr__(self):
        return '<Title %r>' % (self.title)
{do_create.py}
from flaski.database import init_db
# テーブルのクリエイト
init_db()

do_create.pyを実行することで、flaskiディレクトリの下にwiki.dbが出来上がる。
中身を確認してみる。

{confirm_sqllite.}
$ > (flaski)hoge:flaski hoge$ sqlite3 wiki.db 
SQLite version 3.8.5 2014-08-15 22:37:57
Enter ".help" for usage hints.
sqlite> .schema
CREATE TABLE wikicontents (
	id INTEGER NOT NULL, 
	title VARCHAR(128), 
	body TEXT, 
	date DATETIME, 
	PRIMARY KEY (id), 
	UNIQUE (title)
);
{do_insert.py}
from flaski.database import init_db
from flaski.database import db_session
from flaski.models import WikiContent

# idには連番。title、textを指定。dateは日時が勝手に入る(model.pyのデフォルト設定により)
c1 = WikiContent("Flask", "micro framework")  # カラム1:'Flask' カラム2:'micro framework'を指定してインスタンス作成
db_session.add(c1)                            # insert実行
db_session.commit()                           # commit実行
c2 = WikiContent("python", "pppython")        # 以下同上
c3 = WikiContent("kobito", "kakure-momojiri")
db_session.add(c2)
db_session.add(c3)
db_session.commit()

さっきのテーブルを確認してみる。

{confirm_sqllite2.}
(flaski)hoge:flaski hoge$ sqlite3 wiki.db 
SQLite version 3.8.5 2014-08-15 22:37:57
Enter ".help" for usage hints.
sqlite> select * from wikicontents;
1|Flask|micro framework|2016-05-14 15:04:24.246057
2|python|pppython|2016-05-14 15:04:24.246057
3|kobito|kakure-momojiri|2016-05-14 15:04:24.246057

3レコードインサートされていることがわかる。

参考

flaskとSQLiteを連携して、データのGET

さっきのSQLiteに作ったテーブルの値を使って、Webページを表示する。

ソースコード

github

ファイル構成

├── flaski
│   ├── __init__.py
│   ├── database.py
│   └── models.py
├── app.py
├── static
│   └── snake.jpg
└── templates
    ├── index.html
    ├── layout.html
    └── show_content.html

各スクリプト

{app.py}
# -*- coding: utf-8 -*-
"""
 Using SQLAlchemy and Flask get db record.(GET)
"""

from flask import Flask, render_template, abort
from flaski.models import WikiContent

app = Flask(__name__)
app.config['DEBUG'] = True


# 起動されたサーバーの/にアクセスした時の挙動を記述。
# @app.route("/hoge")で記述すれば、http://127.0.0.1:5000/aaでアクセスした時の挙動を記述できる。
@app.route("/")
def hello():
    contents = WikiContent.query.all()
    # index.htmlにcontensを引数に渡して実行。
    return render_template("index.html", contents=contents)

#/<title>を指定することで、index.htmlのtitle=content.titleを指定している。methods=["GET"]で、GETリクエストを指定。
@app.route("/<title>", methods=["GET"])
def show_content(title):
    """
    :param title:modelに対するクエリ文字列
    :return:
    """
    # wikicontentテーブルから、titleでフィルタ(where指定して取得) firstは1行だけ取得するの意味。
    # all()だと、結果を複数リスト形式で取得する。
    content = WikiContent.query.filter_by(title=title).first()
    if content is None:
        abort(404)
    # show_content.htmlを表示。引数にcontentを渡す。
    return render_template("show_content.html", content=content)

if __name__ == "__main__":
    # サーバーの起動
    app.run()

snake.jpg
snake.jpg

{index.html}
{% extends "layout.html" %}
{% block body %}
<h1>Flaski</h1>
<!-- snake.jpgの表示-->
<img src="{{url_for('static', filename='snake.jpg')}}" alt="snake"/>
<ul>
<!-- 引数で渡されたcontentsのforループ-->
{% for content in contents %}
<!-- show_content.htmlを実行。+ {{content.title}}を表示。-->
<li><a href="{{url_for('show_content', title=content.title)}}">{{content.title}}</a></li>
{% endfor%}
</ul>
{% endblock %}
{show_content.html}
{% extends "layout.html" %}
{% block body %}
<!-- contentの内容を使って表示-->
<h1>{{content.title}}</h1>
<div>{{content.body}}</div>
<p>{{content.date}}</p>
<div>{{content.body}}</div>
{% endblock %}

ここまでで、http://127.0.0.1:5000 で以下のページが表示される。
スクリーンショット 2016-05-14 17.56.32.png

それぞれのリンクをクリックでSQLiteの内容が表示される。
例えばpythonのリンクを踏むと、以下のような感じ。
スクリーンショット 2016-05-14 17.57.11.png

SQLiteのpythonの内容を使って、表示されている。(GETができた)
以下のid=2の内容。

{confirm_sqllite2.}
(flaski)hoge:flaski hoge$ sqlite3 wiki.db 
SQLite version 3.8.5 2014-08-15 22:37:57
Enter ".help" for usage hints.
sqlite> select * from wikicontents;
1|Flask|micro framework|2016-05-14 15:04:24.246057
2|python|pppython|2016-05-14 15:04:24.246057
3|kobito|kakure-momojiri|2016-05-14 15:04:24.246057

APIのpostでSQLiteのテーブルに挿入/更新(POST)

SQLiteのテーブルに対し、insertとupdateを実行してみる。

ファイル構成

├── flaski
│   ├── __init__.py
│   ├── database.py
│   └── models.py
└── app.py
{app.py}
# -*- coding: utf-8 -*-
from flask import Flask, render_template, abort, request
from flaski.models import WikiContent
from flaski.database import db_session
from datetime import datetime

app = Flask(__name__)
app.config['DEBUG'] = True


@app.teardown_request
def shutdown_session(exception=None):
    db_session.remove()


@app.route("/")
def hello():
    contents = WikiContent.query.all()
    return render_template("index.html", contents=contents)


@app.route("/<title>", methods=["GET"])
def show_content(title):
    content = WikiContent.query.filter_by(title=title).first()
    if content is None:
        abort(404)
    return render_template("show_content.html", content=content)

@app.route("/<title>", methods=["POST"])
def post_content(title=None):
    if title is None:
        abort(404)
    content = WikiContent.query.filter_by(title=title).first()
    # contentが取得できていなければinsertするため、WikiContentのインスタンスを生成
    if content is None:
        content = WikiContent(title,
                              request.form["body"]
                              )
    # contentが取得できていればupdateするため、bodyの内容とdatetime=現在時刻をセット
    else:
        content.body = request.form["body"]
        content.date = datetime.now()

    # contentの内容をaddしてcommit
    db_session.add(content)
    db_session.commit()
    return content.body

if __name__ == "__main__":
    app.run()

この状態で、app.pyを実行しておく。

コンソール上で、httpリクエストをするため、pip install httpieでhttpieをインストールしておく。

{insert_sqlite.}
# body=test from httpie を指定して更新
http --form POST http://localhost:5000/httpie body="test from httpie"

中身を確認してみると、id=4のレコードが追加された。

{confirm_sqllite3.}
sqlite> select * from wikicontents;
1|Flask|micro framework|2016-05-14 15:04:24.246057
2|python|pppython|2016-05-14 15:04:24.246057
3|kobito|kakure-momojiri|2016-05-14 15:04:24.246057
4|httpie|test from httpie|2016-05-14 19:32:12.075871

今度は更新してみる。

{update_sqlite.}
# body=modified from httpie を指定して更新
http --form POST http://localhost:5000/httpie body="modified from httpie"
{confirm_sqllite4.}
sqlite> select * from wikicontents;
1|Flask|micro framework|2016-05-14 15:04:24.246057
2|python|pppython|2016-05-14 15:04:24.246057
3|kobito|kakure-momojiri|2016-05-14 15:04:24.246057
4|httpie|modified from httpie|2016-05-14 19:35:40.904904

更新されてる。

この状態で、http://localhost:5000 を確認するとhttpieが追加されている。

スクリーンショット 2016-05-14 19.39.02.png

httpieをクリックすると、ちゃんと更新した状態で取得できていることがわかる。
POSTできました。

スクリーンショット 2016-05-14 19.39.35.png
125
138
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
125
138

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?