スポンサーリンク

「Docker」に「flask」+「PostgreSQL」環境構築からデータ取得とページ表示までご紹介。〜 Dockerfile使用 〜

Flask
スポンサーリンク

今回の記事では、「Docker」で「flask」+「PostgreSQL」環境構築からPostgれSQLからデータを取得し、そのデータをページに表示するまでをご紹介する内容です。Dockerfileを準備しているので、細かな環境構築はDockerで省略できます。初学者でもわかるように記載していくので是非参考にしていただければ幸いです。

スポンサーリンク

「Docker」に「Flask」+「PostgreSQL」環境構築

まずは下記のプロジェクト構成を準備してください。

.
└── flask
    ├── app
    └── dev
        ├── Dockerfile
        ├── docker-compose.yml
        └── init_db
            └── init.sql

ではコンテナ立ち上げ用のDockerfileにPythonのイメージとflaskとPostgresSQLの接続クライアントのインストールコマンドを記述します。PostgreSQLはdocker-composeのみで記述していく方針ですのでDockerfileに記述はなしです。

From python:3

RUN pip install --trusted-host pypi.org --trusted-host pypi.python.org --trusted-host files.pythonhosted.org flask

# psycopg2(PostgreSQLクライアント)のインストール
RUN pip install psycopg2

これで準備万端です。Dockerを起動して環境構築してください。

Flaskデータ保存ページ表示

コンテナに入っての作業になります。まずは下記でコンテナIDを接続し、そのコンテナ入りまょう。

docker ps
[起動中のコンテナが表示]現在二つのコンテナが起動しています。
FlaskとPostgreSQLです。Flaskの方に入ります。
docker exec -it [コンテナID] /bin/bash

次にhtmlなどの表示を行うために表示を整えます。今回の記事は下記サイトを参考にしております。下記サイトのDocker-compose.ymlファイルはマウント位置が微妙に間違っているようなのでこちらのサイトの上記ファイルを参考にする以外は基本的に内容は同じになっております。

下記コマンドで構成はできます。

cd usr/local/src/work
mkdir static/css static/js templates
touch app.py static/css/style.css static/js/script.js templates/_layout.html templates/hello.html

コンテナ起動時にマウントしているのでファイル作成はローカルにも反映されます。逆にローカルでフォルダを作成してもコンテナ上に反映されます。

下記ファイルを作成してください。

from flask import Flask, render_template, request, jsonify
import psycopg2

app = Flask(__name__)

def getDbConnection():
    return psycopg2.connect("postgresql://test:test@db:5432/test")
    #"postgresql://[設定したID]:[設定したPS]@[設定したID]:5432/[設定したID]"

def getInputs(con):
    inputs = []
    with con.cursor() as cur:
        cur.execute("SELECT * FROM INPUTS")
        for row in cur:
            inputs.append("[" + str(row[1]) + "]" + row[0])
    return inputs
def insertInput(con, value):
    with con.cursor() as cur:
        cur.execute("INSERT INTO INPUTS (value, input_date) VALUES (%s,current_date)", (value, ))

@app.route("/")
def index():
    return "Hello world!"

@app.route("/hello")
def hello():
    with getDbConnection() as con:
        return render_template("hello.html", title = "Helloページ", inputs = getInputs(con))

@app.route("/hello", methods=["POST"])
def hello_post():
    name = request.form["name"]
    message = request.form["message"]
    inputValue = name + ":" + message
    with getDbConnection() as con:
        insertInput(con, inputValue)
        return render_template("hello.html", title = "Hello(post)ページ", input1 = "入力値=[" + inputValue + "]", inputs = getInputs(con))

@app.route("/api/hello/post", methods=["POST"])
def hello_post_ajax():
    name = request.json["name"]
    message = request.json["message"]
    inputValue = name + ":" + message
    with getDbConnection() as con:
        insertInput(con, inputValue)
    return jsonify({"input1": "入力値=[" + inputValue + "]", "input": inputValue})

if __name__ == "__main__":
    app.run(debug=True, host="0.0.0.0")
<!DOCTYPE html>
<html>
    <head>
        <title>{{title}}</title>
        <script src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.11.1.min.js"></script>
        <script src="/static/js/script.js"></script>
        <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">
        <link rel="stylesheet" href="/static/css/style.css">
    </head>
    <body>
        <nav class="navbar navbar-expand-md navbar-dark fixed-top bg-dark">
          <a class="navbar-brand" href="#">Navbar</a>
          <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarsExampleDefault" aria-controls="navbarsExampleDefault" aria-expanded="false" aria-label="Toggle navigation">
            <span class="navbar-toggler-icon"></span>
          </button>
          <div class="collapse navbar-collapse" id="navbarsExampleDefault">
            <ul class="navbar-nav mr-auto">
              <li class="nav-item active">
                <a class="nav-link" href="#">Home <span class="sr-only">(current)</span></a>
              </li>
              <li class="nav-item">
                <a class="nav-link" href="#">Link</a>
               </li>
              <li class="nav-item">
                <a class="nav-link disabled" href="#">Disabled</a>
              </li>
              <li class="nav-item dropdown">
                <a class="nav-link dropdown-toggle" href="http://example.com" id="dropdown01" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">Dropdown</a>
                <div class="dropdown-menu" aria-labelledby="dropdown01">
                  <a class="dropdown-item" href="#">Action</a>
                  <a class="dropdown-item" href="#">Another action</a>
                  <a class="dropdown-item" href="#">Something else here</a>
                </div>
              </li>
            </ul>
            <form class="form-inline my-2 my-lg-0">
              <input class="form-control mr-sm-2" type="text" placeholder="Search" aria-label="Search">
              <button class="btn btn-outline-success my-2 my-sm-0" type="submit">Search</button>
            </form>
          </div>
        </nav>
        <main class="main">
          {% block content %}
          {% endblock %}
        </main>
    </body>
</html>
{% extends '_layout.html' %}
{% block content %}
    <div class="jumbotron">
        <div class="container">
            <h1 class="display-3">Hello, world!</h1>
            <p>This is a template for a simple marketing or informational website. It includes a large callout called a jumbotron and three supporting pieces of content. Use it as a starting point to create something more unique.</p>
            <p><a class="btn btn-primary btn-lg" href="#" role="button">Learn more »</a></p>
        </div>
    </div>
    <div class="container">
        <form method="POST" action="/hello">
            <div class="form-group">
                <label for="name">名前</label>
                <input type="text" class="form-control" id="name" name="name">
            </div>
            <div class="form-group">
                <label for="message">メッセージ</label>
                <input type="text" class="form-control" id="message" name="message">
            </div>
            <button class="btn btn-lg btn-primary btn-block" type="submit">送信</button>
            <button class="btn btn-lg btn-danger btn-block" type="submit" id="btnSendAjax">非同期送信</button>
        </form>
        <span id="lblInput1" class="hogelabel">{{input1}}</span>
        <ul id="listInputs">
            {% for value in inputs %}
            <li>{{value}}</p>
            {% endfor %}
        </ul>
    </div>
{% endblock %}
body {
    background-color: antiquewhite;
}
$(function() {
    $('#btnSendAjax').click(function () {
        // 入力値取得
        var name = $('input[name=name]').val();
        var message = $('input[name=message]').val();
        $.ajax({
            url: "/api/hello/post",
            type: "POST",
            data: JSON.stringify({name: name, message: message}),
            dataType: "json",
            contentType: "application/json",
            success: function (XMLHttpRequest, textStatus, errorThrown) {
                if (textStatus == 'success' || textStatus == 'nocontent') {
                    // 成功時
                    $('#lblInput1').text(XMLHttpRequest.input1);
                    $('#listInputs').append($("<li>").text(input));
                } else {
                    // エラー時
                    console.error(XMLHttpRequest.responseJSON.Message);
                }
            },
            error: function (XMLHttpRequest, textStatus, errorThrown) {
                // エラー時
                console.error(XMLHttpRequest.responseJSON.Message);
            },
        });
        return false;
    });
});

これでファイル構成は完了です。

下記でflaskを起動してください。

flask run -h 0.0.0.0

ホストのブラウザから localhost:5000 にアクセスして「Hello world!」と表示されたら成功です。

また、「http://localhost:5000/hello」でサンプルページが表示され、「送信」・「非同期送信」ボタンで画面入力した文字がDBに登録されます。確認してみてください。

では今回の記事は以上です。他にも多数のPython関連お記事を記載しているので興味がある方は是非際都内見ていってください。

本記事を読んでいただき感謝です。サイトを訪れていただいた方はプログラミング勉強中かと思いますのでプログラミング勉強のコツを合わせてご紹介。

スポンサーリンク
スポンサーリンク
スポンサーリンク

ブログに関しては500円程度かかりますが、それ以外は無料です。知識の吸収と並行してアウトプットは非常に効率が良いです。テックアカデミーに関しては講座レベルが高いにも関わらず、無料体験や人気口座も大幅値下げがあるので、重点的に学びたいものを無料体験してみてください。

転職時にも、エンジニアからテックアカデミー・Paizaは認知度が高いので、未経験入社採用を行う際履歴書で目に留まります。特にPaizaのスキルレベルA・SなどはIT業界でも評価されます。

テックアカデミー・Paizaの無料登録ができる期間中にぜひご利用してみてください。私も活用経験ありです。

Flask
スポンサーリンク
スポンサーリンク

コメント

  1. […] 【Flask】「Docker」上に「 Flask + PostgreSQL 」環境を構築し、データベースに接… […]

タイトルとURLをコピーしました