News & Topics Stateから皆様へのお知らせ

技術ブログ

【Flask入門:PythonでWebアプリケーションを作ろう】

みなさん、こんにちは!
State代表の高見澤です。

 

 

Flask(フラスク)はPythonのマイクロWebフレームワークで、シンプルかつ柔軟な設計が特徴です。
弊社でも積極採用しているフレームワークの一つになります!
本記事では、Flaskを使って簡単なWebアプリケーションを作成する手順を解説していこうと思います!

 

  • 前提条件
このチュートリアルを進める前に、以下のソフトウェアがインストールされていることを確認してください。
  1. Docker
  2. docker-compose

 

  • ディレクトリ構成
まずは、プロジェクトのディレクトリ構成を確認しましょう。
ディレクトリ構成:
my_flask_app/
 |- app.py
 |- templates/
 |  - index.html
 |  - create_todo.html
 |- static/
 |  - style.css
 |- Dockerfile
 |- requirements.txt
 |- docker-compose.yml
 |- migrations/

– `my_flask_app`: プロジェクトのルートディレクトリ
– `app.py`: Flaskアプリケーションのメインファイル
– `templates`: HTMLテンプレートファイルを配置するディレクトリ
– `static`: CSSやJavaScriptなどの静的ファイルを配置するディレクトリ

 

  • Flaskアプリケーションの作成

 

  1.  `my_flask_app`ディレクトリを作成します。
  2. `my_flask_app`ディレクトリに`app.py`、`index.html`、`create_todo.html`、`create_todo.html、`style.css`ファイルを作成します。
# app.py
from flask import Flask, render_template, request, redirect, url_for
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'postgresql://postgres:mysecretpassword@db:5432/mytodos' # PostgreSQL接続用のURI
db = SQLAlchemy(app)

# ルーティングをBlueprintとして定義します
from flask import Blueprint

# Blueprintオブジェクトを作成します
todos_bp = Blueprint('todos', __name__)

# ToDoモデルを定義します
class Todo(db.Model):
  id = db.Column(db.Integer, primary_key=True)
  title = db.Column(db.String(100), nullable=False)
  completed = db.Column(db.Boolean, default=False)
# 一覧ページ
@todos_bp.route('/')
def index():
  todos = Todo.query.all()
  return render_template('index.html', todos=todos)

# ToDo作成ページ
@todos_bp.route('/create', methods=['GET', 'POST'])
def create():
  if request.method == 'POST':
    title = request.form['title']
    todo = Todo(title=title)
    db.session.add(todo)
    db.session.commit()
    return redirect(url_for('todos.index')) # Blueprint名を指定してリダイレクト
  return render_template('create_todo.html')

# Blueprintをアプリケーションに登録します
app.register_blueprint(todos_bp, url_prefix='/todos')

if __name__ == '__main__':
  db.create_all()
  app.run(host='0.0.0.0', debug=True)
index.html:
<!DOCTYPE html> 
<html>
  <head>
    <title>My ToDo App</title>
    <link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='style.css') }}">
  </head>
  <body>
    <h1>ToDo List</h1>
    <ul>
      {% for todo in todos %}
      <li>{{ todo.title }}</li>
      {% endfor %}
    </ul>
    <a href="{{ url_for('todos.create') }}">Create New ToDo</a> 
  </body> 
</html>
create_todo.html:
<!DOCTYPE html>
<html>
  <head>
    <title>Create New ToDo</title>
    <link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='style.css') }}">
  </head>
  <body>
    <h1>Create New ToDo</h1>
    <form method="post">
      <label for="title">Title:</label>
      <input type="text" id="title" name="title" required>
      <input type="submit" value="Create">
    </form>
    <a href="{{ url_for('todos.index') }}">Back to ToDo List</a>
  </body>
</html>

 

style.css
body {
  background-color: #f5f5f5;
  font-family: Arial, sans-serif;
  text-align: center;
  padding: 50px;
} 

h1 {
  color: #007bff;
}

 

Dockerfile:

# ベースイメージとしてPython公式イメージを使用します 
FROM python:3.9-slim 

# 必要なパッケージをインストールします 
RUN apt-get update && apt-get install -y gcc 

# Pythonの依存パッケージをコピーしてインストールします 
COPY requirements.txt /app/ RUN pip install --no-cache-dir -r requirements.txt 

# カレントディレクトリのコードをコンテナ内の/appにコピーします 
COPY . /app/ 

# Flaskアプリを起動するコマンドを指定します 
CMD [ "python", "app.py" ] 
requirements.txt:
Flask
SQLAlchemy
Flask-Migrate

 

docker-compose.yml:
version: '3.9'

services:
  web:
    build:
    context: .
    dockerfile: Dockerfile
    container_name: my_flask_app
    ports:
      - "8080:5000"
    depends_on:
      - db
    volumes:
      - ./app:/app

  db:
    image: postgres:latest
    container_name: my_postgres_db
    ports:
      - "5432:5432"
    environment:
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=mysecretpassword
      - POSTGRES_DB=mytodos
    volumes:
      - db_data:/var/lib/postgresql/data
volumes:
  db_data:
このdocker-compose.ymlでは、Flaskアプリケーションとデータベースを別々のコンテナとして定義しています。
データベースにはPostgreSQLの公式イメージを使用していますが、必要に応じて他のデータベースも使用できます。

 

では、実際に起動してみましょう。
今回はAWSのクラウド内上で構築しています。

Dockerのバージョン確認
[root@ip-172-31-30-52 my_flask_app]# docker -v
Docker version 20.10.23, build 7155243
[root@ip-172-31-30-52 my_flask_app]# 
[root@ip-172-31-30-52 my_flask_app]# docker-compose -v
docker-compose version 1.6.2, build 4d72027
[root@ip-172-31-30-52 my_flask_app]# 
[root@ip-172-31-30-52 my_flask_app]# 
Dockerコンテナをビルドします。
$ docker-compose build
次に、Dockerコンテナを起動します。

$ docker-compose up

Creating volume "myflaskapp_db_data" with default driver
Starting my_postgres_db
Starting my_flask_app
Attaching to my_postgres_db, my_flask_app
my_postgres_db |
my_postgres_db | PostgreSQL Database directory appears to contain a database; Skipping initialization
my_postgres_db |
my_postgres_db | 2023-07-31 06:03:01.781 UTC [1] LOG: starting PostgreSQL 15.3 (Debian 15.3-1.pgdg120+1) on x86_64-pc-linux-gnu, compiled by gcc (Debian 12.2.0-14) 12.2.0, 64-bit
my_postgres_db | 2023-07-31 06:03:01.782 UTC [1] LOG: listening on IPv4 address "0.0.0.0", port 5432
my_postgres_db | 2023-07-31 06:03:01.782 UTC [1] LOG: listening on IPv6 address "::", port 5432
my_postgres_db | 2023-07-31 06:03:01.785 UTC [1] LOG: listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432"
my_postgres_db | 2023-07-31 06:03:01.790 UTC [27] LOG: database system was shut down at 2023-07-31 06:02:38 UTC
my_postgres_db | 2023-07-31 06:03:01.798 UTC [1] LOG: database system is ready to accept connections
my_flask_app | * Serving Flask app 'app' (lazy loading)
my_flask_app | * Environment: production
my_flask_app | WARNING: This is a development server. Do not use it in a production deployment.
my_flask_app | Use a production WSGI server instead.
my_flask_app | * Debug mode: on
my_flask_app | WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
my_flask_app | * Running on all addresses (0.0.0.0)
my_flask_app | * Running on http://127.0.0.1:5000
my_flask_app | * Running on http://172.18.0.3:5000
my_flask_app | Press CTRL+C to quit
my_flask_app | * Restarting with stat
my_flask_app | * Debugger is active!
my_flask_app | * Debugger PIN: 190-586-524
こんな感じでコンテナが起動します。
これで、Flaskアプリケーションが1つのコンテナに、データベースが別のコンテナにそれぞれ独立して起動されます。FlaskアプリケーションからデータベースにアクセスしてToDoを管理することができます。
2. ブラウザで`http://127.0.0.1:8080`にアクセスします。
※今回はCloud9のためAWSのURLになっています。
画面も表示されてますね!

データベースの中身も見てみましょう。

system_takamizawa:~/environment $ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
3c51b2070fb5 myflaskapp_web "python app.py" 12 minutes ago Up 12 minutes 0.0.0.0:8080->5000/tcp, :::8080->5000/tcp my_flask_app
e69a78ae3c87 postgres:latest "docker-entrypoint.s…" 3 days ago Up 12 minutes 0.0.0.0:5432->5432/tcp, :::5432->5432/tcp my_postgres_db
system_takamizawa:~/environment $
system_takamizawa:~/environment $
system_takamizawa:~/environment $
system_takamizawa:~/environment $ docker exec -it e69a78ae3c87 /bin/bash
root@e69a78ae3c87:/#
root@e69a78ae3c87:/#
root@e69a78ae3c87:/# psql -h localhost -U postgres -p 5432 -d mytodos
psql (15.3 (Debian 15.3-1.pgdg120+1))
Type "help" for help.
mytodos=# \dt
List of relations
Schema | Name | Type | Owner
--------+------+-------+----------
public | todo | table | postgres
(1 row)
mytodos=# \d todo
Table "public.todo"
Column | Type | Collation | Nullable | Default
-----------+------------------------+-----------+----------+----------------------------------
id | integer | | not null | nextval('todo_id_seq'::regclass)
title | character varying(100) | | not null |
completed | boolean | | |
Indexes:
"todo_pkey" PRIMARY KEY, btree (id)
mytodos=#
mytodos=# select * from todo;
id | title | completed
----+-------+-----------
1 | test | f
2 | test | f
3 | test2 | f
(3 rows)

mytodos=#
データもしっかり登録されてますね!
これで、Flaskを使ったシンプルなWebアプリケーションが完成しました!
Flaskの特徴的なルーティングやテンプレートエンジンを活用して、
さらに高度なWebアプリケーションを開発することができます。ぜひ自分のアイデアを試してみてください!

 

Stateではこのようなアプリケーションやアーキテクチャに興味を持っているエンジニアを大募集しております!
一緒に働きたいと思う方はぜひHPからご応募いただけますと嬉しいです!