私は時々、この問題に対して型破りなアプローチをとってきました (他の回答を読んでも、おそらくそれほど型破りではないでしょう)。私はdjangoで試したことがないので、いくつか実験しました。
つまり、古いスキーマに起因する例外をコードでキャッチし、適切なスキーマのアップグレードを適用します。私はこれが受け入れられた答えになるとは思っていません-それはいくつかの場合にのみ適切です(そして、まったくないと主張する人もいます)。しかし、醜いアヒルのような優雅さがあると思います。
もちろん、いつでも本番環境にリセットできるテスト環境があります。そのテスト環境を使用して、スキーマを更新し、それに対してコードを記述します - いつものように。
次に、スキーマの変更を元に戻し、新しいコードを再度テストします。結果のエラーをキャッチし、スキーマのアップグレードを実行してから、エラーのあるクエリを再試行します。
アップグレード関数は、「害を及ぼさない」ように作成する必要があります。これにより、複数回呼び出された場合 (実稼働環境に置かれたときに発生する可能性があります)、1 回だけ動作します。
実際の python コード - これを settings.py の最後に置いて概念をテストしましたが、おそらく別のモジュールに保持する必要があります。
from django.db.models.sql.compiler import SQLCompiler
from MySQLdb import OperationalError
orig_exec = SQLCompiler.execute_sql
def new_exec(self, *args, **kw):
try:
return orig_exec(self, *args, **kw)
except OperationalError, e:
if e[0] != 1054: # unknown column
raise
upgradeSchema(self.connection)
return orig_exec(self, *args, **kw)
SQLCompiler.execute_sql = new_exec
def upgradeSchema(conn):
cursor = conn.cursor()
try:
cursor.execute("alter table users add phone varchar(255)")
except OperationalError, e:
if e[0] != 1060: # duplicate column name
raise
運用環境が最新の状態になったら、この自己アップグレード コードをコードベースから自由に削除できます。しかし、そうしなくても、コードは重要で不要な作業を行っていません。
例外クラス (私の場合は MySQLdb.OperationalError) と番号 (私の場合は 1054 "unknown column" / 1060 "duplicate column") をデータベース エンジンとスキーマの変更に合わせて調整する必要がありますが、それは簡単なはずです。
実行中のSQLが他の問題ではなく問題のスキーマ変更のために実際にエラーであることを確認するために追加のチェックを追加することをお勧めしますが、そうしない場合でも、無関係な例外が再発生するはずです。唯一のペナルティは、例外が発生する前に、アップグレードと不適切なクエリを 2 回試行することになります。
Python について私が気に入っている点の 1 つは、このように実行時にシステム メソッドを簡単にオーバーライドできることです。それは非常に柔軟性を提供します。