Django v1.0 documentation

データベースのサポート状況

revision-up-to:8961 (1.0)

Django は可能な限り全てのデータベースバックエンドをサポートしようとしていま すが、残念ながら全てのサーバが全く同じ仕様というわけではないので、どの機能 をサポートすべきか、どういった仕様を仮定するかといった設計上の判断を下して います。

このドキュメントでは、このドキュメントでは、 Django を使う上で関係のあるデー タベース機能について説明します。ただし、このドキュメントは特定のデータベー スサーバ向けのドキュメントとして書かれたものではなく、リファレンスマニュア ルでもありません。

MySQL に関する注意

Django はデータベースがトランザクションや参照の一貫性 (referential integrity)、 Unicode (UTF-8 エンコーディング) をサポートしていることを想定 して書かれています。好運なことに、 MySQL バージョン 3.23 以降でこれらの機 能全てをサポートしています。従って、 3.23 や 4.0 をバックエンドとして使うの は可能なのですが、 4.1 や 5.0 を使った方がトラブルに巻き込まれにくいでしょ う。

MySQL 4.1

MySQL 4.1 では、文字セットのサポートを大幅に改良しています。 4.1 では、 データベース全体から、テーブル毎、カラム毎にいたるまで個別にデフォルトの文 字セットを指定できます。以前のバージョンでは、サーバ全体に対する文字セット の設定しかできませんでした。また、 4.1 になってはじめてオンザフライで文字セッ トを変更できるようになりました。 4.1 にはビューのサポートもありますが、 Django はまだこの機能をサポートしていません。

MySQL 5.0

MySQL 5.0 では、全てのデータベーススキーマに関する詳細なデータの入った information_schema というデータベースが追加されました。 information_schema が存在すると、 Django はこのデータベースに対して inspectdb 機能を適用します。 5.0 ではまた、ストアドプロシジャのサポート も追加されましたが、 Django はまだこの機能をサポートしていません。

ストレージエンジン

MySQL は複数の ストレージエンジン (以前はテーブルタイプ: table type と呼ばれていたもの) を選択できます。 デフォルトのストレージエンジンはサーバ設定で変更できます。

デフォルトのストレージエンジンは MyISAM です。 MyISAM の短所は、現状ではト ランザクションや外部キーをサポートしていないという点です。一方、 MyISAM は、 現状で、全文インデクスの生成や全文検索をサポートしている唯一のストレージエ ンジンです。

InnoDB エンジンは完全なトランザクション機能と外部キー参照をサポートしてい ます。

BDB エンジンは InnoDB と同様、完全なトランザクション機能を外部キー参照をサ ポートしていますが、やや時代送れになりつつあるようです。

SolidDBFalcon といった その他のストレージエンジン まだまだ圏外の話です。現状では、おそらく InnoDB が最良の選択でしょう。

MySQLdb

MySQLdb は Python から MySQL にアクセスするためのインタフェースです。 Django から利用できる MySQL の全ての機能を使うには、 バージョン 1.2.1p2 以 降が必要です。

Note

MySQLdb を Django から使おうとして ImportError: cannot import name ImmutableSet が出る場合は、おそらく MySQLdb に古い sets.py ファイルが入っていて、 Python 2.4 の同名の組 み込みモジュールと衝突しています。この問題を回避するには、 1.2.1p2 以降 の MySQLdb をインストールしてください。上書きインストールした場合には、 MySQLdb のインストールディレクトリを調べ、以前のバージョンの sets.py が入っていれば除去してください。

データベースを作成する

コマンドラインツールを使って、以下の SQL を発行すれば データベースを作成 できます:

CREATE DATABASE <dbname> CHARACTER SET utf8;

これで、全てのテーブルとカラムがデフォルトで UTF-8 を使うようになります。

コレーションに関する設定

カラムのコレーション設定は、データの保存方法や、文字列の等価性の定義を制御 しています。コレーションはデータベース全体でも、テーブル単位でも、カラム単 位でも設定できます。コレーションの詳細は MySQL のドキュメントで 詳しく解説されています 。いずれの場合でも、コレー ションの設定は直接データベーステーブルに対して行ってください。 Django はモ デル定義でコレーションを設定する方法を提供していません。

デフォルトの構成では、 MySQL は UTF-8 のデータベースに対して utf8_general_ci_swedish コレーションを使います。この設定では、全ての文 字列の等値比較が 大小文字を区別 せず行われます。つまり、 "Fred""freD" はデータベースレベルでは同じ値だとみなされるのです。そのため、デ フォルトのコレーションを使っていると、フィールドに unique 制約をかけた ときに、 "aa""AA" は等しいとみなされ (一意性が破れるので) 同じ カラムに入れられなくなります。

大抵のケースでは、デフォルトの設定はさして問題を起こしません。しかし、特定 のカラムやテーブルで大小文字を区別させたいなら、そのカラムやテーブルに utf8_bin コレーションを指定せねばなりません。その場合、注意すべきなのは、 MySQLdb 1.2.2 を使っていると、 Django のデータベースバックエンドが、データ ベースから取り出した文字列フィールドの値として (unicode 文字列ではなく) bytestring を返すということです。このふるまいは、 常に unicode を返す、と いう Django の通常のやりかたから大きくかけ離れています。コレーションを utf8_bin にして、 bytestring を受け取ったときの扱いは、開発者に委ねられ ています。 Django 自体はこのカラムを問題なく扱えますが、一貫性をもってデー タを処理したければ、 django.utils.encoding.smart_unicode() を何度も 呼び出すことになるでしょう。(データベースバックエンドレイヤとモデルの操作レ イヤは内部的に分離しているため、変換が必要かどうかをデータベースレイヤでは 判断できないので) Django はこの変換に関知しないのです。

MySQLdb 1.2.1p2 を使っているなら、コレーションを utf8_bin にしても、 CharField は unicode 文字列を返します。しかし、 今度は TextField が (Python 標準モジュール array の) array.array を返します。データをデータベースから読み出す ときに、変換に必要な情報が手にはいらないので、 Django 側ではどうしようもあ りません。 この問題は MySQLdb 1.2.2 で解決済み なので、 itf8_bin コレーションで TextField を使いたけ れば、バージョンを 1.2.2 に上げて、バイト文字列として扱うよう勧めます (それ ほど難しくはありません)。

MySQLdb 1.2.1p2 で utf8_bin コレーションの設定されたテーブルを使うのな ら、 django.contrib.sessions.models.Session のテーブル (通常は django_session) や、 django.contrib.admin.models.LogEntry のテーブル (通常は django_admin_log) のコレーションに utf8_collation_ci_swedish (デフォルトのコレーション) を使わねばなりませ ん。これらは標準の Django のテーブルのうち、内部的に TextField を使っているものだからです。

データベースに接続する

設定に関するドキュメント を参照してください。

接続に関する設定は、以下の順に適用されます:

  1. DATABASE_OPTIONS
  2. DATABASE_NAME, DATABASE_USER, DATABASE_PASSWORD, DATABASE_HOST, DATABASE_PORT
  3. MySQL のオプション設定ファイル

別の言い方をするなら、 DATABASE_OPTIONS 内にデータベースの名前を 設定すると、その内容は DATABASE_NAME よりも優先順位が高くなり、 さらに DATABASE_NAMEMySQL のオプション設定ファイル の内容 をオーバライドするということです。

MySQL のオプション設定ファイルを使う例を以下に示します:

# settings.py
DATABASE_ENGINE = "mysql"
DATABASE_OPTIONS = {
    'read_default_file': '/path/to/my.cnf',
    }

# my.cnf
[client]
database = DATABASE_NAME
user = DATABASE_USER
password = DATABASE_PASSWORD
default-character-set = utf8

この他にも、MySQLdb の接続オプションには、 ssl, use_unicode, init_command, sql_mode といった便利なものがあります。詳しくは MySQLdb のドキュメント を参照してください。

テーブルを作成する

Django はスキーマを作成する際にストレージエンジンを指定しません。そのため、 テーブルは常にサーバに設定されたデフォルトのストレージエンジンで作成されま す。作成されるテーブルを特定のタイプにしたければ、データベースサーバのデフォ ルトストレージエンジンを Django で使いたいストレージエンジンに合わせるのが 一番簡単です。

ホスティングサービスを使っていて、サーバのデフォルトのストレージエンジンを 変更できない場合、二つの選択肢があります。

  • テーブルが作成された後に、以下のようなクエリを発行して、ストレージ エンジンを (InnoDB) などに変更します:

    ALTER TABLE <tablename> ENGINE=INNODB;

    テーブルが沢山ある場合には、これは相当骨がおれることでしょう。

  • あるいは、テーブルを作成する前に、 MySQLdb の init_command オプショ ンを使います:

    DATABASE_OPTIONS = {
      ...
      "init_command": "SET storage_engine=INNODB",
      ...
      }

    このように設定しておくと、接続時にデフォルトのストレージエンジンが変更 されます。ただし、テーブルが全て作成され、運用環境で動き始めたら、この オプションを外しておかねばなりません。

  • syncdb 時にストレージエンジンを変更するもう一つの方法は、 Wiki の AlterModelOnSyncDB に記載されています。

BooleanField に関する注意

MySQL には直接的な BOOLEAN カラム型がないので、 Django は BooleanField の値を TINYINT カラムを使って 0 または 1 で保存します。詳しくはモデルフィールドのドキュメントを参照してくだ さい。ただし、フィールドの値を出力したり、値が TrueFalse でなけ ればならないような場合を除いて、特に問題はありません。

SQLite に関する注意

バージョン 3.3.5 以前の SQLite には、 ORDER_BY パラメタの扱いかたに バグがあります 。そのため、クエリセットメソッド extra() を使って select のパラメタを指定しようとすると問題を引き起 こします。このバグは、 OperationalError: ORDER BY terms must not be non-integer constants とい うメッセージを出力します。 SQLite のバージョンを 3.3.6 に上げ、 pysqlite2 モジュールを更新すれば、問題を解決できます。

バージョン 3.3.6 は 2006 年の 4 月にリリースされており、現在手に入る各プラッ トフォームのほとんどのバイナリ配布物で、Python から pysqlite2sqlite3 を介して使える SQLite は新しいバージョンなので、あまり大きなイ ンパクトはありません。

ただし、 Windows の場合、 Python 2.5 の公式の安定版リリースのバイナリ配布物 には (今のところ 2.5.2 も)、 SQLite 3.3.4 が組み込まれているため、バグが確 認されています。このため (Django 1.0 で) 3 つのテストスイートが失敗します。 この問題は、上で述べたように、 新しいバージョン SQLite が組み込まれた pysqlite2 (pysqlite-2.x.x.win32-py2.5.exe) をダウンロードしてインス トールすれば解決できます。 Python 2.6 には新たなバージョンの SQLite が付属 する予定なので、この問題の影響を受けないはずです。

上記のプラットフォームを使っていて、 pysqlite や SQLite を更新する必要 があるなら、Django のソースツリーの django/db/backends/sqlite3/base.py ファイルを手で編集して、 sqlite3 より pysqlite2 が先に import され るように変更してください。

Oracle に関する注意

Django はバージョン 9i 以降の Oracle データベースサーバ をサポートしてい ます。 Django の regex および iregex クエリオペレータを使うには、 バージョン 10g 以降の Oracle を使う必要があります。 バージョン 4.3.1 以降の cx_Oracle ドライバが必要です。

Oracle で python manage.py syncdb コマンドを動かすには、データベースユー ザに以下のコマンドを実行できる権限が必要です:

  • CREATE TABLE
  • CREATE SEQUENCE
  • CREATE PROCEDURE
  • CREATE TRIGGER

Django のテストスイートを実行させるには、 さらに 以下の権限が必要です:

  • CREATE USER
  • DROP USER
  • CREATE TABLESPACE
  • DROP TABLESPACE

データベースへの接続

Oracle を使う場合、 Django の settings.py は以下のように設定します:

DATABASE_ENGINE = 'oracle'
DATABASE_NAME = 'xe'
DATABASE_USER = 'a_user'
DATABASE_PASSWORD = 'a_password'
DATABASE_HOST = ''
DATABASE_PORT = ''

tnsnames.ora ファイルや、 SID として扱われる名前 (上の例では "xe") を使わない場合は、以下のように DATABASE_HOST および DATABASE_PORT を設定してください:

DATABASE_ENGINE = 'oracle'
DATABASE_NAME = 'xe'
DATABASE_USER = 'a_user'
DATABASE_PASSWORD = 'a_password'
DATABASE_HOST = 'dbprod01ned.mycompany.com'
DATABASE_PORT = '1540'

DATABASE_HOSTDATABASE_PORT は、両方とも指定するか、 両方とも空にするかどちらかにしてください。

テーブルスペース

Oracle ベースのシステムでパフォーマンス向上に使われているパラダイムとして、 「 テーブルスペース (tablespace)」によるディスクレイアウトの構築がありま す。 db_tablespace オプションを MetaField クラスに追加する と、 Oracle バックエンドはテーブルスペースを利用します (バックエンドがテー ブルスペースをサポートしなければ、 Django はこのオプションを無視します)。

モデルのテーブルにテーブルスペースを指定するには、モデルの内部クラス Metadb_tablespace オプションを指定します。モデル全体とは別のテー ブルスペースをフィールドのカラムインデクスに指定したければ、フィールドのコ ンストラクタに db_tablespace を指定します。カラムごとにインデクスを生成 しない場合には、 db_tablespace オプションは無視されます:

class TablespaceExample(models.Model):
    name = models.CharField(max_length=30, db_index=True, db_tablespace="indexes")
    data = models.CharField(max_length=255, db_index=True)
    edges = models.ManyToManyField(to="self", db_tablespace="indexes")

    class Meta:
        db_tablespace = "tables"

上の例では、 TablespaceExample モデルの生成するテーブル (モデルテーブルと多対多のリレーションのテーブル) は、 tables という名前 のテーブルスペースに保存されます。 name フィールドと、多対多リレーショ ンテーブルのインデクスは indexes テーブルスペースに保存されます。 data フィールドもインデクスを生成しますが、このインデクスのテーブルスペー スは指定されていないので、デフォルトの挙動としてテーブルスペース tables に保存されます。

Django 1.0 で新たに登場しました.

db_tablespace オプションのデフォルト値を指定するには、 DEFAULT_TABLESPACE および DEFAULT_INDEX_TABLESPACE 設 定を使います。これらの設定は、組み込みの Django アプリケーションや、ソース コードをいじれないアプリケーションに対してテーブルスペースを指定する場合に 便利です。

Django 自体にはテーブルスペースを作成する機能はありません。 テーブルスペースの作成や管理の方法は、 Oracle のドキュメント を参照して ください。

名前に関する制約

Oracle は名前の長さを 30 文字以下に制限しています。この制限に合わせるために、 バックエンドは識別子名を切り詰めて、最後の 4 文字を MD5 のハッシュ値で置き 換えます。

NULL 値よび空文字列

Django は通常、 NULL ではなく空文字列を使うようにしていますが、 Oracle はこ れらを別々のものとして扱います。この問題を回避するには、 Oracle バックエン ドは空文字列を値として受け入れるフィールドに null=Ture オプションを 強制的に付加します。データベースから値を取り出すとき、フィールドの値が NULL であれば、そのフィールドの値は実際には空文字列であるとみなし、値も暗黙のう ちに空文字列に変換されます。

TextField への制限

Oracle バックエンドは TextFieldNCLOB カラム形式で保存します。 Oracle は、一般に LOB カラムに以下の制約を課しています:

  • LOB カラムは主キーにできません。
  • LOB カラムはインデクス化に使えません。
  • LOB カラムは SELECT DISTINCT できません。従って、Oralce バックエン ドを使っていて、 TextField カラムを含むモデルに対して QuerySet.distinct を行うとエラーを引き起こします。このエラーを避け るには、 distinct() クエリの対象モデルから TextField を除去し、 TextField を持つ他のモデルを定義しておいてリレーションを張ってくだ さい。