図書館情報学を学ぶ

はてなダイアリーで公開していたブログ「図書館情報学を学ぶ」のはてなブログ移行版です。

DjangoでModelを変更したときに注意すること

Djangoネタ再び。Djangoチュートリアルを進めている人向けの記事です。やたら分かりにくい文章になってしまいました・・・・・・もっと技術的な話をするスキルを身につけないと。
下の記事に間違いなどあれば是非コメントください。

1

例えば、Django上でlibというアプリケーションを作成して、モデルを定義するとDjangoでは以下のようなコードでModelを定義します。

from django.db import models

class Person(models.Model)
   name = models.CharField(maxlength=200)

class Book(models.Model)
   title = models.CharField(maxlength=200)
   pub_date = models.DateTimeField('date published')
   author = models.ForeignKey(Person.name)

書誌情報を管理するデータベースを構築するとして、まず簡単に本に関するデータモデルBookと、著者などの人に関するデータモデルPersonを定義してみます。
Personにはnameという属性があり、ここには200文字以内で名前を入力することができます。
Bookにはtitle・pub_date・authorの3つの属性があり、それぞれ本のタイトル、出版年月日、著者名を表しています。このうち、authorはPersonと関連づけられています。例えばJohnという名前を持ったPersonが登録されていると、BookのauthorとしてJohnを選択することができます。
上のようにモデルを定義した上で、コマンドライン上で以下のコマンドを実行します。

python manage.py syncdb

すると、上で定義したモデルに対応したデータがSQL上で自動的に定義されます。つまり、SQL文を書かずともデータベースの構築を行うことができます。非常に便利ですね。

2

また、後で新たなModelを定義してsyncdbを実行しても、新しいModelに対応したテーブルを作成してくれます。以下のようなコードを書いたとします。

from django.db import models

class Person(models.Model)
   name = models.CharField(maxlength=200)

class Book(models.Model)
   title = models.CharField(maxlength=200)
   pub_date = models.DateTimeField('date published')
   author = models.ForeignKey(Person.name)

class Library(models.Model)
   name = models.CharField(maxlength=200)

上のコードには新たにLibraryというモデルが追加されています。この場合にsyncdbをすると、ちゃんとLibraryに対応したテーブルを作成してくれます。

2

ただし、以下のようなコードに修正すると、問題が発生します。

from django.db import models

class Person(models.Model)
   name = models.CharField(maxlength=200)

class Book(models.Model)
   title = models.CharField(maxlength=200)
   pub_date = models.DateTimeField('date published')
   author = models.ForeignKey(Person.name)
   library = models.ForeignKey(Library.name)

class Library(models.Model)
   name = models.CharField(maxlength=200)

Bookモデルに所蔵している図書館の情報を登録するために、Bookモデルにlibraryという属性を追加しています。今までの作業からすると、既にあるモデルを書き換えても、syncdbを実行すれば自動的にデータベース側も修正してくれると期待すると思います。
しかし、これを実行するとlibraryに対応したテーブルが無いというエラーが出ます。
実は、Djangoでは既に定義されたモデルを書き換えても自動的に修正してくれません。修正点は手動でSQLを書いて修正する必要があります。

3

Djangoチュートリアルを読むと、これは意図的なものだそうです。データベースの列を勝手に書き換えるなどの処理は、他のプログラムに影響を与えてしまうため、安易に自動処理をするとトラブルが起こりやすい。そのため、修正するときは手動で行って、影響が起こらないか確認しながら行って欲しい、という考えによるものだそうです。
つまり、「スタートは面倒見てやるけど、その後の処理は自分でちゃんとやれよ」ということですね。
上のようなモデルに対応したSQLは、次のように書きます。

ALTER TABLE lib_book ADD (
   library INT, FOREIGN KEY (lib_book.library) REFERENCES (lib_library.id)
); 

このSQLMySQLなどのデータベース管理システム上で実行すると、修正したモデルと対応をとることができ、エラーも起こらなくなります。

4

一見面倒くさい作業のような気もしますが、作業を通してデータベース上では実際にどのように定義されているのかが分かって大変ためになりました。Djangoの良いところは過保護になりすぎず、フレームワークの機能を利用しながら、基本的なスキルを習得しやすいような仕様になっている点ですね。自転車の練習をしている子どもの後ろで倒れないように支えてあげているのだけど、しばらくするとそっと手を離す父親みたいな感じがしますね。