【対象】:これからPython/FlaskでWebアプリを作る人
【ゴール】:PythonとFlaskの基礎を動くコードで押さえる
1.Pythonの特徴
-
クロスプラットフォーム
主要OSで動作 -
豊富なライブラリが存在
Web(Flask, FastAPI, Django)、数値計算(NumPy), データ処理(pandas), 機械学習(scikit-learn, PyTorch, TensorFlow) -
汎用性
スクリプト/API/Web/データ分析まで広く対応 -
フロント分離
Webではバックエンド=Python, フロント=React等で役割分担が一般的
2.基本文法(型・コレクション)
#数値型
i: int = 10
f: float = 3.14
#文字列(str)
s = "あいうえお"
print(s[0]) # 'あ'
#真偽値(bool)
is_ok = True
#リスト(list)
numbers = [1, 2, 3, 4, 5]
print(numbers[0]) # 1
print(numbers[-1]) # 5
print(numbers[1:4]) # [2, 3, 4]
numbers.append("apple")
numbers.insert(1, "banana")
numbers.pop()
numbers.sort()
numbers.sort(reverse=True)
#タプル(tuple)
t = (1, 2, 3)
# t[0] = 9 # エラー
#辞書(dict)
person = {"name": "Taro", "age": 25, "sex": "man"}
print(person["name"])
person["height"] = 163
person["name"] = "Goro"
del person["age"]
#四則演算
a + b # 加算
a - b # 減算
a * b # 乗算
a ** b # 累乗
a / b # 浮動小数
a // b # 切り捨て除算
a % b # 余り
a += 1 # インクリメント
#if文
num = int(input("0より大きい整数を入力してください: "))
if num > 0:
if 0 < num < 10:
print("入力した数は0以上10より小さい数です")
else:
print("入力した数は10以上の整数です")
else:
print("0以上の整数を入力してください")
#for文
# Ex1
total = 0
for i in range(5):
total += i
print(total)
# Ex2
fruits = ["apple", "banana", "grape"]
for f in fruits:
print(f)
# Ex3
person = {"name": "Taro", "age": 25, "sex": "男"}
for k, v in person.items():
print(f"{k}: {v}")
# Ex4
nums = [n for n in range(4)]
print(nums)
# Ex5
keys = ["math", "english", "science"]
scores = [82, 70, 90]
d = {k: s for k, s in zip(keys, scores)}
print(d)
# Ex6
pairs = []
for i in range(4):
for j in range(3):
pairs.append([i, j])
print(pairs)
# Ex7
numbers = [1, 2, 3]
for n in numbers:
print(n)
else:
print("全ての数字を出力しました")
#while文
num = 0
while num < 10:
num += 1
if num == 3:
continue
print(num)
if num > 5:
break
#関数・可変長引数・lambda
def add(a, b=0):
return a + b
print(add(1))
print(add(1, 2))
def profile_create(*args, **kwargs):
print(f"位置引数: {args}")
print(f"キーワード引数: {kwargs}")
profile_create("東京", "ひなた", age=27, job="engineer")
def list_build(*args, my_list=None):
if my_list is None:
my_list = []
for e in args:
my_list.append(e)
return my_list
print(list_build(1, 2, 3))
lambda_add = lambda x, y: x + y
print(lambda_add(3, 5))
data = [(1, "apple"), (3, "banana"), (2, "berry")]
sorted_data = sorted(data, key=lambda x: x[0])
print(sorted_data)
#例外処理
try:
result = 10 / 0
except ZeroDivisionError:
print("エラー:0で割り算はできません")
def convert_to_int(value):
try:
return int(value)
except ValueError:
print(f"ValueError: '{value}' は整数に変換できません")
def get_item(lst, index):
try:
return lst[index]
except IndexError:
print(f"IndexError: インデックス {index} は存在しません")
def read_file(file_name):
f = None
try:
f = open(file_name, "r", encoding="utf-8")
print(f.read())
except FileNotFoundError:
print(f"FileNotFoundError: {file_name} が見つかりません")
finally:
if f is not None:
f.close()
print(f"ファイル {file_name} を閉じました")
age = int(input("あなたの年齢を入力してください: "))
def check_age(a):
if a < 0:
raise ValueError("年齢には0以上の値を入力してください")
print(f"あなたの年齢は {a} 歳です。")
try:
check_age(age)
except ValueError as e:
print(f"入力エラー: {e}")
3.Flaskの基礎
-
小〜中規模Webアプリ向けフレームワークが可能
-
直感的なルーティング, テンプレート(Jinja2), DB連携(SQLAlchemy)が可能
3-1.Flaskのインストールと最小アプリ
-Flaskのインストール
pip install Flask
- Flaskの最小アプリ
from flask import Flask, render_template
app = Flask(__name__)
@app.route("/")
def index():
return "<h1>Hello World!</h1>"
if __name__ == "__main__":
app.run(debug=True)
3-2.テンプレート継承
<!-- templates/base.html -->
<!doctype html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>メモアプリ</title>
</head>
<body>
{% block content %}{% endblock %}
</body>
</html>
<!-- templates/index.html -->
{% extends "base.html" %}
{% block content %}
<h1>メモアプリ</h1>
{% endblock %}
3-3.Flask×SQLAlchemyでDBモデル定義
-
SQLAlchemyのインストール
pip install flask_sqlalchemy flask_migrate -
モデルの定義方法
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate
app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///memo.db"
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False
db = SQLAlchemy(app)
migrate = Migrate(app, db)
class Memo(db.Model):
id = db.Column(db.Integer, primary_key=True)
content = db.Column(db.String(1000), nullable=False)
created = db.Column(db.DateTime, server_default=db.func.now())
3-4.フォーム送信とDB登録
<form action="{{ url_for('add_memo') }}" method="POST">
<div>
<label>メモ内容</label>
<input type="text" name="content" required>
</div>
<button type="submit">メモを追加する</button>
</form>
from flask import request, redirect, url_for, render_template
@app.route("/add_memo", methods=["GET", "POST"])
def add_memo():
if request.method == "POST":
content = request.form.get("content")
try:
new_memo = Memo(content=content)
db.session.add(new_memo)
db.session.commit()
return redirect(url_for("index"))
except Exception:
db.session.rollback()
return "There was an issue adding your memo", 500
return render_template("add_memo.html")
**3-5.レコード削除の実装
**
<form method="POST" action="{{ url_for('delete_memo', memo_id=memo.id) }}">
<button type="submit">メモを削除する</button>
</form>
@app.route("/memos/<int:memo_id>/delete", methods=["POST"])
def delete_memo(memo_id):
memo = Memo.query.get(memo_id)
if memo is None:
return "Memo not found", 404
try:
db.session.delete(memo)
db.session.commit()
return redirect(url_for("index"))
except Exception:
db.session.rollback()
return "There was an issue deleting your memo", 500
3-6.よくあるエラーと対処
- ValueError 値の中身が不正 int("abc")
- IndexError インデックス範囲外 lst[99]
- KeyError 辞書にキーがない d["age"]
- TypeError 型不一致 5 + "abc"
- ZeroDivisionError 0除算 10/0
- AttributeError 属性がない "abc".not_exist()
- NameError 未定義変数 print(x)
- FileNotFoundError ファイルなし open("no.txt")
- ImportError import失敗 ライブラリ未インストール
- IndentationError インデントずれ コロン抜けなど
- SyntaxError 文法エラー 括弧・クォート不整合
- BuildError(Flask) url_forの引数名不一致 ルートとurl_forを合わせる
4.まとめ
- URL変数名・インデント・フォームmethod・DBセッションを丁寧に扱うと事故が減る
- FlaskはReactなどと組み合わせて「バックエンド+フロント分離」もやりやすい