LoginSignup
15
16

More than 5 years have passed since last update.

djangoで1ファイルでORMの挙動を確認する方法

Last updated at Posted at 2015-03-07

djangoで1ファイルでORMの挙動を確認する方法

以前 1ファイルでhello worldを作る方法 を書きましたが。
djangoで最も試してみたい事柄はORM部分かもしれません。そのORM部分を1ファイルだけで試す方法についてです。

1ファイルで試すには、ちょっとした細工が必要ですが、最近のdjangoではそれもそれなりに手軽にできるようになりました。

具体的には以下のような作業が必要になります。

  • settingsをpython側から設定する
  • djangoのApplicationRegistryにmodelを登録する
  • 各modelのテーブルを生成する

settingsをpython側から設定する

settingsの設定がない場合には、以下のような例外が出てしまいます。

django.core.exceptions.ImproperlyConfigured: Requested setting DEFAULT_INDEX_TABLESPACE, but settings are not configured. You must either define the environment variable DJANGO_SETTINGS_MODULE or call settings.configure() before accessing settings.

エラーメッセージの通り、DJANGO_SETTINGS_MODULEを環境変数として登録しておくかsettings.configure()を呼びましょう。
最低限必要な設定は以下の通りです。

from django.conf import settings

settings.configure(
    DEBUG=True,
    DATABASES={"default": {
        "ENGINE": "django.db.backends.sqlite3",
        "NAME": ":memory:"
    }},
    INSTALLED_APPS=[__name__]
)

DEBUG=Trueはsqlのquery結果を出力する際に必要なので付けておいた方が良いでしょう。また、DBの設定は必要です。ここではsqliteのオンメモリDBを指定しています。INSTALLED_APPSについては後述するmodelの登録の際に指定を忘れていた場合ManyToManyの関連が上手く動作しない様になってしまいます。

djangoのApplicationRegistryにmodelを登録する

django.setup()を呼んでください。これによりdjango.apps.registry.Appspopulate()が呼ばれます。この中でdjangoのregistryにmodelが登録されていきます。これがなかった場合にはModel.save()を呼んだタイミングなどで以下のようなエラーが発生します。

django.core.exceptions.AppRegistryNotReady: Models aren't loaded yet.

また注意点として、定義するmodelにはapp_labelを設定してください。これがないとmodelクラスを生成できません。以下のようなエラーが出てしまいます。

IndexError: list index out of range

定義する時には以下の様にするということです。

class X(models.Model):
    name = models.CharField(max_length=255, default="foo", blank=True)

    class Meta:
        app_label = __name__

各modelのテーブルを生成する

通常はpython manage.py migrateなどでDBのテーブルを生成しますが。1ファイルの場合にはその手順がありません。他の方法を考える必要があります。
例えば、テーブルを生成する関数を作ってあげます。

from django.db import connections
from django.core.management.color import no_style


def create_table(model):
    connection = connections['default']
    cursor = connection.cursor()
    sql, references = connection.creation.sql_create_model(model, no_style())
    for statement in sql:
        cursor.execute(statement)

    for f in model._meta.many_to_many:
        create_table(f.rel.through)


# 一つ一つ生成していく必要がある
create_table(X)

まとめ

以上のことを一通りまとめると以下の様になります。これで手軽にmodelの挙動を確かめる事ができますね。

# -*- coding:utf-8 -*-
import django
from django.db import models
from django.conf import settings
from django.db import connections
from django.core.management.color import no_style


settings.configure(
    DEBUG=True,
    DATABASES={"default": {
        "ENGINE": "django.db.backends.sqlite3",
        "NAME": ":memory:"
    }},
    INSTALLED_APPS=[__name__]
)


def create_table(model):
    connection = connections['default']
    cursor = connection.cursor()
    sql, references = connection.creation.sql_create_model(model, no_style())
    for statement in sql:
        cursor.execute(statement)

    for f in model._meta.many_to_many:
        create_table(f.rel.through)


class X(models.Model):
    name = models.CharField(max_length=255, default="foo", blank=True)

    class Meta:
        app_label = __name__


if __name__ == "__main__":
    import logging
    logging.basicConfig(level=logging.DEBUG)
    django.setup()
    create_table(X)

    xs = X.objects.bulk_create([X(id=1), X(id=2), X(id=3)])

    print(X.objects.count())
15
16
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
15
16