django(python)初心者がDB更新でハマった話

こんにちは、kochosです。

今日はdjango学び始めた僕がORM(Object-relational mapping)どハマりした初歩的なお話をします。

ORMって???

正確なことはGoogle先生に聞いてくださいね。普段業務でJavaを使ってOracleDBを直接使っているときとの対比で感覚的に説明します。

Oracleを使ってSQLを叩くとき、DBのあるテーブルからデータを取得する場合には以下のように書きますね。

select * from user_table where user_id = 1;

テーブルを覗きに行っているイメージです。

一方でORMというのは、「感覚的にいうと」取得したいデータのイメージをプログラミング言語で書いて、プログラミング言語がそれを翻訳してテーブルからデータを引っ張ってくるイメージです。

例えばdjangoで書くとこんな感じですかね。

user = User.objects.get(id=1)

処理っぽい感じが伝わるでしょうか。RubyのフレームワークであるRailsとかも似たような感じで書きます。

僕がマイグレーションでどハマりした話

さて本題に入りますと、普段の業務ではあんまりORM使ってないので、djangoで一歩ずつと勉強しておりました。ある日既存データの更新がしたかったのです(もちろんORMで)
そこで私がやったのは

training = Training.objects.get(pk=1) # primary_keyが1のオブジェクトを取得
Training.objects.all().values('time_to') #登録されているレコードのtime_to属性の値を取得


→<QuerySet [{'time_from': None}, {'time_from': None}]>つまり何もセットされていない

training.time_to = '17:00' # trainingインスタンスのtime_toに17:00を設定
 training.save() #データを反映

ここで改めてセット状況を確認


Training.objects.all().values('time_to') #登録されているレコードのtime_to属性の値を取得


→<QuerySet [{'time_from': None}, {'time_from': None}]>つまり何もセットされていない

なんでた、、、

となったわけです。

ここでしばらく悩んだんですが、ふと​頭によぎりました。

「このモデル(テーブル構造みたいなもの)、もともと日付型で定義してたけど、そのあと文字型に変更したなあ、、:


変更したときは以下をやってたんです。

python manage.py makemigrations bodymaker


これでマイグレーションファイルはできています。なのでフレームワーク上はカラムの型は変更されています。

が、もうお気づきかもしれませんが、DBに対する変更(migrate)をしていなかったんです。

つまりテーブル自体の変更が反映されていなかった。だからうまく更新できてなかったのです。

そこに気がついた僕はマイグレートを実行しました。

python manage.py migrate


これを実行したあとにもう一度上記の更新をしたところ、無事に更新が反映されました。

直にSQL打っているとすぐに気が付けるエラーも、ORMだと気が付けなかったりするので、ORMを使っている時には裏側でどんなSQLが発行されているのかを意識するのが大切だと感じました。

例えばdjangoだと.queryをつける、Railsならto_sqlをつけるとかですね。

まだまだ初心者の私ですが、ハマったことは初歩的なことだったとしても恥かしがらずに共有できればと思います!


この記事が気に入ったらサポートをしてみませんか?