Make組ブログ

Python、Webアプリや製品・サービス開発についてhirokikyが書きます。

Djangoのマイグレーションで実行される処理(とSQL)を確認する方法

Djangoマイグレーションで実行される処理(とSQL)を確認する方法を説明します。

先日の記事では「Djangoマイグレーションを無停止で反映する方法」を説明しましたが、そのためにはマイグレーションでどんなSQLが実行されるかが重要になります。

blog.hirokiky.org

もちろんマイグレーションファイルを開いて見れば分かりますが、Djangoのコマンドから便利に確認したり、実際に発行されるSQLを確認しておくほうが安全です。

実行されるマイグレーションのプランを確認する

Djangomigrate --plan コマンドを使って、実行されるマイグレーションのプランを確認できます。 この例では blog アプリの 00010002 というマイグレーションが適応されていない状態です。

python manage.py migrate --plan
Planned operations:
blog.0001_initial
    Create model Post
blog.0002_post_published_at
    Add field published_at to post

--plan を見るとそれぞれのマイグレーションでどのような処理が実行されるかが分かります。 この例では以下の意味になります。

  • 0001: モデルPostを作成する
  • 0002: postにpublished_atフィールドを追加する

両方のマイグレーションファイルともテーブルやカラムを追加するものなので、(基本的に)Webアプリのリリース前にマイグレーションを実行できます。

マイグレーションで実行されるSQLを確認する

migrate --plan で内容を確認できるとはいえ、実際にマイグレーションで実行されるSQLを確認しておくほうが安心です。 Djangoにおいてマイグレーションで実行されるSQLを確認するには、 sqlmigrate コマンドを使います。 アプリケーション名 <app_name>マイグレーションの名前 <migration_name> を指定して使います。

python manage.py sqlmigrate <app_name> <migration_name>

例えば blog アプリの 0002_post_published_at.py マイグレーションファイルで実行されるSQLを確認するには、以下のようにします。

python manage.py sqlmigrate blog 0002

こうすることで 0002_post_published_at.py が反映されるときに実行されるSQLが表示されます。

BEGIN;
--
-- Add field published_at to post
--
ALTER TABLE `blog_post` ADD COLUMN `published_at` datetime(6) NULL;
COMMIT;

SQLの内容を見ることで、マイグレーション実行時にどのような処理がデータベースに行われるかが分かります。 Webアプリを無停止のままマイグレーションを反映するときは、このSQLの内容に応じてどのようにリリースすべきかが変わります。

本番環境と同じデータベースバックエンドを使って確認しよう

ただし、 sqlmigrate の結果は settings で使われているデータベース(DATABASES 設定の内容)に応じて結果は変わります。 必ず運用している環境と同じデータベースバックエンドを使ってSQLを確認しましょう。 例えば、上記の例はMySQLバックエンドで出力しましたが、SQLite3バックエンドでは以下のような別のSQLになります。

BEGIN;
--
-- Add field published_at to post
--
CREATE TABLE "new__blog_post" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "published_at" datetime NULL, "body" text NOT NULL);
INSERT INTO "new__blog_post" ("id", "body", "published_at") SELECT "id", "body", NULL FROM "blog_post";
DROP TABLE "blog_post";
ALTER TABLE "new__blog_post" RENAME TO "blog_post";
COMMIT;

まとめ

以下2つのコマンドを使ってマイグレーションの内容を確認しましょう。

これでマイグレーションSQLの内容が分かったらWebアプリを無停止でマイグレーションをできるかを検討しましょう。

blog.hirokiky.org

DjangoマイグレーションをWebアプリが無停止のまま安全に反映する方法

f:id:hirokiky:20191101104548j:plain

Djangoはデータベースマイグレーションの機能を持っています。 ですが、 実際、Djangoマイグレーションってどう使うの? という疑問が多いかと思います。

docs.djangoproject.com

この記事では、 マイグレーションを稼働中のアプリケーションに、無停止でどう反映すれば良いのか を説明します。 前提としてWebアプリ、データベースは本番環境に1系統づつあるとします。

基本的に無停止でマイグレーションを実行するのは 絶対に安全という方法ではないので、動作確認などをして慎重に反映する必要があります

無停止でマイグレーションを反映する基本

マイグレーション無停止で行う場合、「マイグレーションとアプリのリリースはどちらを先にすべきか」 という話になります (マイグレーションをするということは、アプリケーションの変更も必要になります)。

上記ではない場合、アプリケーションを停止する時間が必要になります(アプリケーションを停止、マイグレーションを実行、アプリケーションを変更して実行する)。

マイグレーションの3種類

アプリケーションを無停止のままマイグレーションを反映するには、まずマイグレーションの種類を判断する必要があります。 ここでは大きく分けて3つのマイグレーションと考えられます。

追加、変更、削除それぞれのマイグレーションをどう反映するのかが重要です。

動作確認は必要

無停止でマイグレーションを実行するのは、Webアプリが誤動作を起こすリスクを持っています。 方法は後述しますが、アプリケーションの作り方によって問題が発生し得ます。また、動作が保証される状態でもありません。 本番環境へリリースする前に、マイグレーションを実行しても問題ないか開発環境で必ず動作確認しましょう

マイグレーションを実行するタイミング

アプリケーションを無停止でマイグレーションを実行するには種類と実行するタイミングが重要です。 それぞれマイグレーションの種類ごとに、稼働中のWebアプリにマイグレーションを実行する方法を説明します。

テーブル、カラムを追加するマイグレーションの場合

テーブル、カラムの追加をするマイグレーションは、アプリのリリースより前に実行できます。

テーブル、カラムが増えたところで、Django製のアプリケーションには基本的に影響がありません。 ですので、Webアプリケーションのリリース前にマイグレーションを実行します。

  1. マイグレーションを実行する
  2. Webアプリケーションをリリースする

f:id:hirokiky:20191101104548j:plain
追加するマイグレーションを無停止で反映

テーブルやカラムが増えても、既存のDjango製のWebアプリケーションの動作や、通信量には影響がありません。 DjangoSQLを実行するときに、取得するフィールド(カラム)を全て指定するからです。

ただし、DjangoのQuerySetでextraやrawを使う場合や、生SQLを実行する場合はこの限りではありません。 アプリケーション内に影響するプログラムは無いかは事前にちゃんと確認しましょう。

カラムの削除をするマイグレーション

カラムの削除をする場合は、先にWebアプリケーションをリリースします。 アプリケーションが先にリリースされることで削除対象のフィールド(カラム)は使われなくなります。

  1. Webアプリケーションのリリース
  2. マイグレーション実行

f:id:hirokiky:20191101104612j:plain
削除するマイグレーションを無停止で反映する方法

削除対象のカラムが完全に使われなくなったことを確認してからマイグレーションを実行できます。 ただし「カラムが絶対にWebアプリ内で使われていない」ことを確認するのは大変です。慎重に確認した後、マイグレーションを実行しましょう。

カラムを変更するマイグレーション

カラムを変更するマイグレーションの場合は注意が必要です。 マイグレーションを無停止で実行できるかどうかはマイグレーションの内容によります。

例えばカラム名を変更するマイグレーションは無停止ではリリースできません。 どちらを先に実行しても、稼働中のWebアプリケーションに影響を与えます。

f:id:hirokiky:20191101104027j:plain
変更するマイグレーションを反映する方法

  • 無停止でリリースできない
    • テーブル、カラム名の変更
    • カラムの型を変更
  • 無停止でリリースできる(可能性がある)
    • カラムの最大長などを変更
    • インデックスの追加、削除

マイグレーションの内容を理解して、無停止で安全に反映できるかを確認しましょう。 カラムの最大長変更なども、稼働中のアプリケーションに影響を与えますので注意しましょう。

マイグレーションが複数ある場合

カラムの追加するマイグレーション、削除するマイグレーションが複数ある場合、Webアプリが無停止のままでは同時に反映できません。 その場合はひとつひとつマイグレーションの実行と、アプリケーションのリリースをする必要があります。

Djangoマイグレーションを1つづつ実行する方法は別のブログ記事で説明します。

まとめ

Webアプリを無停止のままマイグレーションを反映するには、マイグレーションの内容を理解してリリースする必要があります。

改めてになりますが、本番環境にリリースする前には開発環境で動作確認しましょう。 開発環境で、無停止でリリースできることを確認してから本番環境でリリースしましょう。

Djangoマイグレーションの内容を確認する方法や、1つづつ反映する方法は別のブログ記事で説明します。

続きはこちらです!

blog.hirokiky.org

ブログ記事に書くPythonコードはPEP8を厳密に守るべき?

ブログに書くコードスニペットはPEP8を厳密に守るべきでしょうか。

pep8-ja.readthedocs.io

ブログ記事に書くPythonコードはPEP8を気にしすぎなくて良いのでは

僕はブログ記事に書くPythonコードは、PEP8をそこまで気にしないで良いと思っています。 ブログに書くコードはブログの記事中で読まれるので、普通のコードのようにエディターなどで読まれるコードとは違うからです。

  • エディターでプログラムを読むときとブログで読むときは違う
  • 開発プロジェクト内では必要な、書き方の統一がブログには不要
  • てきとうに伝えたいだけなので厳密に気にするのは面倒

もちろんブログ記事内でも読みにくいコードは記事にとって良くないですし、PEP8を全く考慮しない書き方を「この書き方が良いものだ」と伝えるのは良くないです。 ですが、自分の記事で厳密に気にしすぎたり、まして他人のブログ記事に「PEP8準拠していないぞ」とわざわざ言う必要は無いと思います。 僕もPEP8は守ろうと思っていますが、ブログ記事内で守っていないこともあります。

PEP8を守って読みにくいとき

ブログ記事にPythonコードを書いて、PEP8を守ると読みにくくなるときがあります。 例えば以下のようなPythonコードを見ると、 main() 関数の上2行が間延びして見えるときがあります。

import os

HERE = os.path.dirname(__file__)


def main():
    print(HERE)

このくらいのコードをいくつか連続して書くと、ブログ記事は読みにくくなると思います。 PEP8違反にはなりますが、行を詰めたほうが読みやすい場合もあると思います。

HERE = os.path.dirname(__file__)

def main():
    print(HERE)

むしろ import os も分かりきっているので書かなくて良いかなという気すらします。 ブログという媒体においては、下の例のほうが大切だと思います。

なにかの戒律を厳密に守る(強いる)ことよりも、場所や場合によって一番良い方法で書くのが良いのではないでしょうか。

PEP8を読んでみる

PEP8を開いてみると、あまり厳密に気にしすぎるのは違うよねと書いています。

### 一貫性にこだわりすぎるのは、狭い心の現れである

スタイルガイドは一貫性に関するものです。
このスタイルガイドに合わせることは重要ですが、プロジェクトの中で一貫性を保つことはもっと重要です。
一番重要なのは、特定のモジュールや関数の中で一貫性を保つことです。

しかし、一貫性を崩すべき場合があることも知っておいてください
 - つまり、このスタイルガイドが適用されない場合があります。
疑問に思ったときは、あなたの判断を優先してください。
他の例を調べ、一番良さそうなものを決めて下さい。そして、躊躇せずに質問して下さい!

https://pep8-ja.readthedocs.io/ja/latest/

まとめ

PEP8は可読性のために大切だと思いますが、ブログ記事に書くPythonコードまでそこまで細かく気にする必要は無いと思います。

他にオススメの記事

blog.hirokiky.org

invokeで実行されるコマンドをプロジェクトルートから実行する方法

invoke(pyinvoke)というプロジェクト管理用のツールを使っていたときに出た疑問の解決方法を説明します。 とはいえ、私自身もまだこの方法で良いのか疑問なので、より良い方法を知っている人はぜひ教えてください。

invoke(pyinvoke)とは

プロジェクトでの開発を進める際に、よくあるコマンド操作をまとめておくことがよくあります。 例えば不要なファイルを削除したり、フォーマッターを適用したり、本番用にビルドしたりなどがあります。 invoke(pyinvoke)を使うとPythonでシェルでのコマンド操作を簡単に書けるようになります。

www.pyinvoke.org

invokeでプロジェクトルートから実行する

invoke でコマンドを実行(c.run(...))するときは、invoke ... を実行したパスでコマンドが実行されます。 invoke のタスクを定義したファイルは以下のように走査されますが、実行パスは変わりません。

docs.pyinvoke.org

ですが、例えばフォーマッターを全体に適応したいときなどはプロジェクトルートからコマンドを実行したくなります。 例えば以下のようなプロジェクト構成のとき、 mymodule 以下で invoke ... としても、 tasks.py を含むディレクトリーから実行したいときです。

+- tasks.py
+- setup.py
+- mymodule
    +- foo.py
    +- bar.py

そういう場合は、以下のように tasks.py を書くと良いでしょう。

import os

from invoke import task


HERE = os.path.dirname(__file__)


@task
def mytask(c):
    c.run("...")

こうすると、 invoke mytask はプロジェクトルート(tasks.py を含むディレクトリー)で実行されます。 私はプロジェクト全体のフォーマットを整えるタスクに活用しています。

@task
def format(c):
    c.run("black .")
    c.run("isort -rc .")

このプロジェクトルートから実行する方法については、invokeのドキュメントやIssueを調べても良い回答は見つかりませんでした。 唯一近そうなのがこのIssueでした。

github.com

もしより良い方法を知っている方がいれば教えてください。

仕事の精度、家政の精度。なぜ核家族の育児は大変なのか

家事、育児の話題続きで申し訳ないです。 今僕が育児休暇中なので考える機会が多いのです。

ですがこういう課題の多い分野ほどビジネスチャンスが大きいと思うので、記録として残しておきます。

仕事の"精度"と家政の"精度"は大きく違う

仕事と家政の違いは何でしょうか?働きに外に出る人と専業主夫/婦の揉める種として以下のような話を聞きます。

  • 私の外仕事のほうが大変だ
  • 私は毎日24時間仕事してるようなものだ

僕は仕事と家政の違いは以下のように分けて考えるべきだと思います

  • 一般的な仕事: 80%〜120%の精度の仕事を、週に5回、8時間働く
  • (自宅における)家政、育児: 40%〜60%の精度の仕事を、週に7回、12時間働く

一般的に仕事というのはまず100%が当たり前という世界です。 手順があるのであれば、その手順を間違えないことが大切になってきます。そのうえでプラスアルファを出せればより良いと捉えられます (もちろんクリエイティブな仕事はこの限りではありませんが、基本にある考え方は理解してもらえると思います)。

一方、自宅における家政というのはかなり精度が低くて良いです。 四角い角と丸く掃いたところで、売上が落ちるようなことはありません。 一日トイレ掃除をサボっても、まぁ生きてはいけるでしょう。お客様商売のようなシビアさはありません (気を遣う必要がある親族と同居している、配偶者が細かい点に厳しい場合などは精度が求められますが、これも基本的な部分は理解してもらえると思います)。

育児の大変さは、精度を高めようとすることだ

育児が大変なのは、その家政において精度が求められる(求めてしまう)ことにあります。 内的な要因としても「命を預かる以上」という責任感が産まれますし、「よく育てたい」という気持ちや、親戚の期待、子供への社会の厳しさ(泣き声に苦情がくる)もあって仕事に高精度を求められがちです。 ですが前述したようにこの仕事は言ってしまえば7D24Hに近い仕事です。そこで100%以上の精度を常に出していると燃え尽きてしまいます。

たしかに「子供が泣かないようにしないと」「ちゃんと消毒しないと」「ミルクをあげてちゃんと体重を増やさないと」など気にすべきことは多いです。ですがこれらすべてに100%の精度を求めると仕事が多すぎます。 「まぁ泣いてもいいや」「サカザキ菌なんてそうそういないやろ」「それなりに体重増えてるし大丈夫やろ」くらいの雑な気持ちでいかないといけません。

なので 育児は仕事ができる人ほど辛い ものだと思います。 予測不能で、論理的に解釈不可能で、膨大な仕事があるからです。でも、雑で良いんです。

育児は核家族には不可能。でもなぜ外注しにくいのか

育児をしてみて感じたのは、人類の子供というものが核家族で育てるようにできていないことです。 子供の世話をしながら家事も仕事もするというのは不可能です。現代においては社会保障制度がある程度充実しているので誤魔化しながら運用されていますが、そもそも不可能と言うべきです。

とはいえ親族に頼れというのも前時代的です。 では「代行」を使うのはなぜ難しいのでしょう。

それは「家事・育児代行」とすると「一般的な仕事」になり、80%〜120%の精度が求められるようになるから です。 とくに育児であれば命を預かる仕事なので、精度は100%以上を求められるでしょう。それを発注するとなると自分でやるより割高になるのは無理ありません。

100%の仕事として24時間の仕事を依頼するとなると、もちろん数万円単位の支払いとなります。 家政として自分でやったり親戚に任せるのであれば、50%くらいの精度ですが、それほど高額な仕事にはなりません(一日子供を親に預けていて、5万円、10万円を支払うことはないでしょう)。

だからといって「50%の精度の育児」を買う人はいないでしょう。命を預ける仕事だからです。 この 仕事に期待する精度の意識差 が、核家族を追い込むことになっています。

解決策は?

僕が考えるなかでは、信頼をベースにした仕事の依頼しかないと感じています。 お金が動くと100%精度の仕事を求められるので、贈与経済のような信頼を元にしたやり取りがうまくいくかもしれません。 信頼し合える人たち同士が、お互いに50%の仕事を担保し合えるような関係です。 今の社会では親族くらいしかありませんが、そういったコミュニティーを形成するサービスというのは考えられます(田舎の閉鎖的になったコミュニティーにも問題はあるので)。

ともあれ、局所最適化した都市型経済というのは、東京で毎日通勤電車に乗る単身者に向いたものなのだなと感じています。

皆さんのアイディアで、ぜひ日本の核家族(そして僕)を救ってください。

育児が大変なのは基準や業務の曖昧さからくる?

免責: この記事は個人の戯言です この記事に政治、宗教的な立場はありません。また、何かを他人に訴える文章でもありません。 僕がただ感じたことを書いているだけです。

本文

育児において何が苦労するのか。作業自体の労力もちろんですが、僕は情報の曖昧さ(基準や業務内容の曖昧さ)からくる余分な疲れというのも多いのではないか?と思っています。 「どういうこと?」「基準?業務?」と思う人にほど読んで欲しいところです。育児や家政には基準、業務設計や正解がないから大変だという話をします。

(これは早朝に、ミルクをあげるブサイクな僕です)

例えば新生児を育てたことがある人なら、誰しも以下のような疑問を持ったことだと思います

  • 授乳間隔はどれほど守るべきなのか
  • 授乳の時間はどれくらいかけて良いものなのか
  • なぜ毎度沸騰して70℃以上にしたお湯でミルクを作るべきなのか
  • 哺乳瓶を洗う洗剤は、必ず乳幼児用を使うべきなのか

色々な情報を調べたり教えて貰えるので知ることはできるでしょう。産科の看護師さんに教えてもらったり、親に教えてもらったり、役所の勉強会で知ったり、ネットで調べて知ったりできます。でも情報のソースが多くて混乱することもあることと思います。

僕が腑に落ちないと言っている点は何でしょうか。それは「基準」がないことです。調べたり教えて貰っても、明確な答えが常に100%あるわけではありません(知っているものは後述します)。 義務教育やプロトコル、規格のような基準、ある種の「バイブル」はなく、あくまでも個々人として対応する必要があります。

情報がどれも曖昧な理由は2つ考えられます

  1. 安全性の絶対的な基準がないこと
  2. 子供による個体差の違いが大きいこと

言ってしまえば、育児(や家政)は業務設計や組織管理ができていない職場です。 そのゴール設定、ルール、手順、定款、労基を自分で作る必要がある場だとすら言えます。

育児においてその基準があれば親のストレスは随分軽減されると感じています。 例えば調乳や授乳の基準があれば「これだけやっとけば大丈夫。それ以上は趣味範囲の頑張り」というのが分かって気持ちも楽になるでしょう。 例えば赤ちゃんが泣いたときも、「100dBまではご近所さんからも許容されている」と分かっていれば「泣かせておけばいいや」と思えるかもしれません。

何が言いたいかというと、僕は今世界で一番、世の親というものに共感しているということです。

1. 安全性の基準はどこに

まず目的が「子供の健康的な発育」ということで、安全性をどこまで求めるべきかという基準はそもそも存在しません(究極はもちろん個人の自由になります)。 大昔の人類であれば滅菌も殺菌も気にすること無く生きてきたことと思いますが、それに併せて疾病や死亡リスクも高かったんだろうと想像できます。だが現代ではどこまで求めれば良いのでしょうか?

現代においては知られているリスクをもとに、なるべくリスクを減らすようにしたいことと思います。後述するように比較的信頼できる基準はあるので、それを参考にするのが良いでしょう。

でも世の情報にはお気持ちレベルのものも多いです。例えば哺乳瓶などの滅菌をする「ミルトン」は水で洗い流す必要はないとメーカーが表示していますが、ネットで調べると「いちおう水で洗い流しています」という情報も見つけられます。それはもはや神経質すぎではないでしょうか。

個人がそうなるのも理解できます。基準がないがゆえ、どこまで「リスクを許容したうえで楽をできる」かが分からないからです。 信頼できる基準があって、それを信頼すれば、もう少し楽な気持ちで育児に望めるのではないでしょうか。

調乳のガイドライン

安全性の基準は探せばあります。もちろんメーカーの製品が書いてあることは、個人の想像よりは信頼できるでしょう。 また、例えば調乳については、WHOとFAOの出したガイドラインを訳したものを厚生労働省が公開しています。

www.mhlw.go.jp

これについては、以下のように明確に書かれており分かりやすです

  • 前提として無菌状態の調整粉乳を作ることは難しい
  • E Sakazaki、Salmonellaの感染リスクを下げたい
  • 以下の手順をガイドラインとして推奨
    • 哺乳瓶などは滅菌すること
    • 一度沸騰させたお湯で調乳すること
    • 70℃以上のお湯で調乳すること
    • 調乳後2時間以内に使用しなかったミルクは捨てること

また、誕生後6ヶ月までは母乳を推奨するとも書かれています。 これは原典が2007年のガイドラインなので古い情報かもしれませんが、無いよりは良い情報です。 これで「70℃以上で調乳」の根拠も分かります。

2.個体差

ここまで基準やなんやと書いていますが、正直、基準を用意するなど無理なことも理解しています。 それは子供の個体差が大きいからです。

もちろん調乳やら疾病リスクについては基準は設けられるでしょう。 でも「どういう姿勢で授乳すべきか」「どのくらいの感覚で授乳すべきか」「洗剤には何を使うべきか」「なぜ泣くのか」「便の頻度はどのくらいか」などは個体差が大きすぎて基準が設けられません。 例えばウチの娘はそれほど泣かなきません(でしたが、一ヶ月くらいになる頃によく泣くようになりました)。ミルクは飲みますが、飲んでるときの休憩はよくするなどあります。僕の赤ちゃん時代は石鹸に弱く沐浴剤を使っていたそうですし、子供によってはベビーオイルで肌荒れするなど個体差が多くあります。

よくよく考えてみれば、大人も自分自身も個体差があり、自分の健康にすらもよく分かっていません。 健康についても数多くの宗教がありますし、どれが正解かも分かりません。僕はボディーソープはダブが良いですし、皆、気がつけば低糖質ダイエットにハマっています。だがそれの恒久的な正解はなく個人の好みの問題です。

育児が難しい理由は、それら「宗教の選択」が自己責任の範疇を少し超えていることです。 あくまでも子供という他人を面倒みないといけないのに、自己責任の範疇で面倒を見る必要があることです。 これが育児ストレスやノイローゼの大きな一因になっていると思います。マジメな人ほど、100%の安全に寄せようとして心労を重ねているように見えます。

言ってしまえば誰しもが素人ながらルールもなく、絶対の正解もなく、あいまいな成果を求められている状態です。管理体制のない組織のようですね。 管理視点での仕事において大切なのは、業務設計と、ゴールの基準と、評価制度 だ(と僕個人は考えている)。育児や家政にはそれがなく、自分や家庭内で策定する必要があります。 実に自主性を求められる職場です。もはや小さな起業ではないでしょうか?

まとめ

僕が何をあなたに伝えたいか、ということはありません。 新生児の育児は大変だねという共感です。 強いて言うなら、もう少し業務設計やマネジメント的な視点を持ち込むと良いかもしれません。 以下の本や僕のブロク記事をオススメします。

気が向けば、「家政のための業務設計入門」というブログ記事でも書こうと思います。

はじめの一歩を踏み出そう―成功する人たちの起業術

はじめの一歩を踏み出そう―成功する人たちの起業術

blog.hirokiky.org

blog.hirokiky.org