0
2

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 1 year has passed since last update.

【python】勉強メモ 速習Flask②

Last updated at Posted at 2022-12-24

1. はじめに

今回は、SQLiteを使い投稿したデーターをDBに保存するところまで行いたいと思います。

2. 全体の流れ

1.事前準備(SQLite3のインストール)
2.共通化
3.投稿内容のDB登録(今回のメイン)
4.DB登録処理(今回のメイン)

1. 事前準備 SQLite3のインストール

  1. SQLite3 ダウンロードページへ移動。

  2. 「Precompiled Binaries for Windows」まで移動し、
    「sqlite-tools-win32-x86-3360000.zip」をダウンロード
    SQL-1.PNG

  3. ダウンロードしたら、任意の場所でZIPファイルを解凍。

  4. 解凍すると、sqldiff.exe、sqlite3.exe、sqlite3_analyzer.exeのファイルが存在する。

  5. 3つのファイルを設置するためのフォルダを作成する。私の場合は、以下にsqliteという
      フォルダを作成する。
      C:\PC-Work\dockerenv\sqlite

  6. sqliteフォルダー内に、sqldiff.exesqlite3.exesqlite3_analyzer.exeをコピーします。

  7. コマンドから実行出来るように、Pathを通す。

  8. Pahtが通ったか、以下のコマンドを実行。

 $env:path.split(";")

sqlitへPATHが通ったことを確認

C:\PC-Work\dockerenv\sqlite
  1. sqlalchemyのインストール(仮想環境内で実行すること)
pip install flask-sqlalchemy
  1. slqalchmeyがインストールされたことを確認
pip list
Package          Version
---------------- -------
click            8.1.3
colorama         0.4.6
Flask            2.2.2
Flask-SQLAlchemy 3.0.2
greenlet         2.0.1
itsdangerous     2.1.2
Jinja2           3.1.2
MarkupSafe       2.1.1
pip              22.3
setuptools       65.5.0
SQLAlchemy       1.4.45
Werkzeug         2.2.2

前回の続きから

ディレクトリ構造

pydir/
 ┣myproject/ ->このディレクトリで仮想環境有効化のコマンドを実行&flask runコマンドもここで
   ┣venv/
   ┣instance/
    ┣blog.db ->今回作成
   ┣hello.py
   ┣app.py -> 今回作成
   ┣templates/
    ┣hello.html
    ┣index.html ->今回作成
    ┣base.html ->今回作成
    ┣create.html ->今回作成

仮想環境の有効化

.venv\Scripts\activate.ps1

app.pyファイル作成

New-Item app.py

app.py記述

app.py
from flask import Flask
from flask import render_template

app = Flask(__name__)

@app.route("/")
def hello():
    return render_template('index.html')

templatesフォルダに移動して、index.htmlファイルを作成

New-Item index.html

index.html記述

index.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <h1>ブログアプリケーション</h1>
    <article>
        <h2>記事1</h2>
        <p>作成日時: 2022/12/17 10:00</p>
        <p>記事1の内容</p>
    </article>
    <article>
        <h2>記事2</h2>
        <p>作成日時: 2022/12/17 11:00</p>
        <p>記事2の内容</p>
    </article>
</body>
</html>

環境変数設定

$env:FLASK_APP = "app"

デバッグモード

$env:FLASK_ENV = "development"

Flaskの起動

flask run
'FLASK_ENV' is deprecated and will not be used in Flask 2.3. Use 'FLASK_DEBUG' instead.'FLASK_ENV' is deprecated and will not be used in Flask 2.3. Use 'FLASK_DEBUG' instead.'FLASK_ENV' is deprecated and will not be used in Flask 2.3. Use 'FLASK_DEBUG' instead. * Serving Flask app 'app'
 * Debug mode: on
WARNING: This is a development server. Do not use it in a production deployment. Use a 
production WSGI server instead.
 * Running on http://127.0.0.1:5000
Press CTRL+C to quit
 * Restarting with stat
'FLASK_ENV' is deprecated and will not be used in Flask 2.3. Use 'FLASK_DEBUG' instead.'FLASK_ENV' is deprecated and will not be used in Flask 2.3. Use 'FLASK_DEBUG' instead.'FLASK_ENV' is deprecated and will not be used in Flask 2.3. Use 'FLASK_DEBUG' instead. * Debugger is active!
 * Debugger PIN: 261-206-630

ブラウザでhttp://127.0.0.1:5000/へアクセス
Flask-1.PNG

ここまでが事前準備。
エラーが出た場合は、前回までのコードの見直しが必要。


2. 共通化

templatesフォルダ内に、HTMLで共通で利用するためのファイル(base.html)を作成する。
{% block content %} {% endblock %} の間に、index.html内の {% block content %} から
{% endblock %} の内容が埋め込まれる。

base.html記載

base.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <!-- ここに、index.htmlの共通化要素(記事1とか記事2などの内容)が埋め込まれる -->
    {% block content %}
    {% endblock %}
</body>
</html>

index.htmlが、base.htmlを読み込むための編集
{% extends "base.html" %} で、base.htmlの

が読み込まれる。
index.html
{% extends "base.html" %} <!--追記 -->
{% block content %} <!--追記 -->
<h1>ブログアプリケーション</h1>
<article>
    <h2>記事1</h2>
    <p>作成日時: 2022/12/17 10:00</p>
    <p>記事1の内容</p>
</article>
<article>
    <h2>記事2</h2>
    <p>作成日時: 2022/12/17 11:00</p>
    <p>記事2の内容</p>
</article>
{% endblock %} <!--追記 -->

ブラウザで、127.0.0.1:5000にアクセスすると、前回と変わらない画面が表示されれば、共通化成功です。

3. 投稿内容のDB登録

投稿は、HTTPのPOSTというメソッドを使い、DBに投稿(送信)される。

app.py
from flask import Flask
from flask import render_template
from flask_sqlalchemy import SQLAlchemy
from datetime import datetime
import pytz

app = Flask(__name__)
app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///blog.db" # 今回作成するDB名
db = SQLAlchemy(app)

# 以下の部分がClassを使ってDBへPOSTするデーターを定義している。
# db.String()は、入力可能な文字数を定義
# nullable=Falseは、nullでPOSTはできないように定義
class Post(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    title= db.Column(db.String(50), nullable=False)
    body = db.Column(db.String(300), nullable=False)
    created_at = db.Column(db.DateTime, nullable=False,
                    default=datetime.now(pytz.timezone('Asia/Tokyo')))

@app.route("/")
def hello():
    return render_template('index.html')

DB作成(SQLiteを使用)

仮想環境内で以下のコマンドを実行すること。
対話モードで実施(app.pyがあるところで)

python
Python 3.11.0 (main, Oct 24 2022, 18:26:48) [MSC v.1933 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>>
>>> from app import app, db
>>> with app.app_context():
...     db.create_all()
...
>>> exit()

上記コマンドは分かりにくいのでキャプチャーも載せておきます。
キャプチャ-1.PNG

成功すると、dbが作成されます。
SQL-2.PNG

新規登録画面を作成するため、create.htmlを作成する。

create.html
{% extends "base.html" %}
{% block content %}
<h1>新規登録</h1>
<form method="POST">
    <label for="title">タイトル</label>
    <input type="text" name="title">
    <label for="body">内容</label>
    <input type="text" name="body">
    <input type="submit" value="新規登録">
</form>
{% endblock %}

index.htmlでは、「新規作成画面」へ遷移するためのボタンを作成する。
<a href="/create" role="button">新規作成画面</a>を追加。

index.html
{% extends "base.html" %}
{% block content %}
<h1>ブログアプリケーション</h1>
<!-- ボタン作成 -->
<a href="/create" role="button">新規作成画面</a> 
<article>
    <h2>記事1</h2>
    <p>作成日時: 2022/12/17 10:00</p>
    <p>記事1の内容</p>
</article>
<article>
    <h2>記事2</h2>
    <p>作成日時: 2022/12/17 11:00</p>
    <p>記事2の内容</p>
</article>
{% endblock %}
app.py
from flask import Flask
from flask import render_template
from flask_sqlalchemy import SQLAlchemy
from datetime import datetime
import pytz

app = Flask(__name__)
app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///blog.db"
db = SQLAlchemy(app)

# 以下の部分がClassを使ってDBへPOSTするデーターを定義している。
# db.String()は、入力可能な文字数を定義
# nullable=Falseは、nullでPOSTはできないように定義
class Post(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    title= db.Column(db.String(50), nullable=False)
    body = db.Column(db.String(300), nullable=False)
    created_at = db.Column(db.DateTime, nullable=False,
                    default=datetime.now(pytz.timezone('Asia/Tokyo')))

@app.route("/")
def hello():
    return render_template('index.html')

# 新規登録画面へ遷移するためのルーティング追加
@app.route("/create")
def create():
    return render_template('create.html')

base.htmlは、修正なし。

base.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <!-- ここに、HTMLの共通化が埋め込まれる -->
    {% block content %}
    {% endblock %}
</body>
</html>

127.0.0.1:5000にアクセス
ブログのTop画面に「新規作成画面」ボタンが表示される。「新規作成画面」をクリック。
Flask-2.PNG

Flask-4.PNG

新規作成画面でタイトルと内容を入力し、新規登録ボタンをクリック
Flask-5.PNG

エラーとなる
Flask-6.PNG

app.py側でPOSTを受け付ける仕組みを作っておかなければならない。上記では、POSTで送信しているが、HTTPはデフォルトでGET送信するため。

app.py側で、GETとPOSTの両方を受け付ける様に変更を行う。

app.py
from flask import Flask
from flask import render_template
from flask_sqlalchemy import SQLAlchemy
from datetime import datetime
import pytz

app = Flask(__name__)
app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///blog.db"
db = SQLAlchemy(app)

class Post(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    title= db.Column(db.String(50), nullable=False)
    body = db.Column(db.String(300), nullable=False)
    created_at = db.Column(db.DateTime, nullable=False,
                    default=datetime.now(pytz.timezone('Asia/Tokyo')))

@app.route("/")
def hello():
    return render_template('index.html')


@app.route("/create", methods=['GET', 'POST']) # ここを追加
def create():
    return render_template('create.html')

再度、「新規作成画面」から新規登録を行う。
Flask-7.PNG
以下の画面が表示されれば成功です。無事、POST(登録内容がDBへ送信)される。
ただし、DBには、送信したデーターは登録されていない。
Flask-8.PNG

4. DB登録処理

以下からDB登録処理
処理内容としては、POST後に、**db.session.commit()**でDBへコミットし、return redirect('/')で
トップページにリダイレクトを行う。
上記をif文
内に記載している。

app.py
from flask import Flask
from flask import render_template, request, redirect # 追加
from flask_sqlalchemy import SQLAlchemy
from datetime import datetime
import pytz

app = Flask(__name__)
app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///blog.db"
db = SQLAlchemy(app)

class Post(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    title= db.Column(db.String(50), nullable=False)
    body = db.Column(db.String(300), nullable=False)
    created_at = db.Column(db.DateTime, nullable=False,
                    default=datetime.now(pytz.timezone('Asia/Tokyo')))

@app.route("/")
def hello():
    return render_template('index.html')


@app.route("/create", methods=['GET', 'POST']) # ここを追加
def create():
    # requestがPOSTだったら
    if request.method == 'POST':

        # request.form.get()でフォームで入力した情報を取得(事前に、requestのimport必要)
        title = request.form.get('title')
        body = request.form.get('body')
     
        post = Post(title=title, body=body)

        # DBにpostされてきたデーターを追加(add)する
        db.session.add(post)

        # 変更を保存
        db.session.commit()

        # DB登録後、トップページにリダイレクト
        return redirect('/')

    # POSTではない場合、つまり、GETでアクセスした場合の処理
    else:
        return render_template('create.html')
create.html
{% extends "base.html" %}
{% block content %}
<h1>新規登録</h1>
<form method="Post">
    <label for="title">タイトル</label>
    <input type="text" name="=title">
    <label for="body">内容</label>
    <input type="text" name="=body">
    <input type="submit" value="新規登録">
</form>
{% endblock %}
index.html
{% extends "base.html" %}
{% block content %}
<h1>ブログアプリケーション</h1>
<!-- ボタン作成 -->
<a href="/create" role="button">新規作成画面</a> 
<article>
    <h2>記事1</h2>
    <p>作成日時: 2022/12/17 10:00</p>
    <p>記事1の内容</p>
</article>
<article>
    <h2>記事2</h2>
    <p>作成日時: 2022/12/17 11:00</p>
    <p>記事2の内容</p>
</article>
{% endblock %}

ブラウザで、127.0.0.1:5000にアクセス。
Flask-7.PNG

新規作成画面をクリック
Flask-8.PNG

新規登録画面に遷移するので、「タイトル」「内容」を入力し、新規登録ボタンをクリックするとDBへ登録が行われ
最初の画面に戻る。エラーがでなければOK。
登録した内容が表示されない理由は、まだ、登録したデーターを取得して、表示する処理を追加していないため。

Flask-9.PNG

DB登録の状況確認については、次回。

0
2
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
0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?