web-dev-qa-db-ja.com

Djangoのモデルとしてデータベースビューを使用できますか?

データベースに作成したビューをDjangoビューのソースとして使用したいと思います。

これは、カスタムSQLを使用せずに可能ですか?

****** 13/02/09更新***********

多くの回答が示唆するように、データベースで独自のビューを作成し、models.pyで定義することでAPI内で使用できます。

ただし、いくつかの警告:

  • manage.py syncdbはもう機能しません
  • ビューの名前の先頭には、他のすべてのモデル(テーブル)と同じものが必要です。たとえば、アプリが "thing"と呼ばれる場合、ビューはthing_ $ viewnameと呼ばれる必要があります。
60
spence91

Django 1.1以降、 Options.managed を使用できます。

古いバージョンでは、ビューのModelクラスを簡単に定義して、他のビューと同様に使用できます。 Sqliteベースのアプリを使用してテストしたところ、正常に動作するようです。ビューの「プライマリキー」列の名前が「id」でない場合は必ずプライマリキーフィールドを追加し、ビューが「app_classname」と呼ばれない場合はメタオプションでビューの名前を指定してください。

唯一の問題は、Djangoがテーブルを作成しようとするため、「syncdb」コマンドが例外を発生させることです。それを防ぐには、models.pyとは異なる別のPythonファイルで「ビューモデル」を定義します。このように、Djangoは、models.pyをイントロスペクトしてアプリ用に作成するモデルを決定するときにそれらを認識しないため、テーブルを作成しようとしません。

32
Ferdinand Beyer

この質問に遭遇する人のための更新(Googleまたは他の何から)...

現在Djangoには データベーステーブルを管理せずにモデルを定義する)への簡単な「適切な方法」があります

Options.managed

デフォルトはTrueで、Djangoはsyncdbに適切なデータベーステーブルを作成し、reset管理コマンドの一部としてそれらを削除します。 Djangomanagesデータベーステーブルのライフサイクル。

Falseの場合、このモデルに対してデータベーステーブルの作成または削除操作は実行されません。これは、モデルが他の方法で作成された既存のテーブルまたはデータベースビューを表す場合に役立ちます。これは、managedFalseである場合のonlyの違いです。モデル処理の他のすべての側面は、通常とまったく同じです。

93
drdaeman

Postgres 9.4およびDjango 1.8。のビューを使用してモデルを実装しました。

次のようなカスタム移行クラスを作成しました。

# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from Django.db import migrations


class Migration(migrations.Migration):

    dependencies = [
        ('myapp', '0002_previousdependency'),
    ]

    sql = """
    create VIEW myapp_myview as
     select your view here
    """

    operations = [
        migrations.RunSQL("drop view if exists myapp_myview;"),
        migrations.RunSQL(sql)
    ]

私はいつものようにモデルを書きました。それは私の目的のために機能します。

-makemigrationsを実行すると、モデル用の新しい移行ファイルが作成され、手動で削除されました。

完全な開示-jsonbデータ型から派生したビューを使用しており、ON UPDATE INSTEADルールを記述していないため、ビューは読み取り専用です。

12
eceppda

Djangoの単一データベースの制限を回避するために、MySQLを使用するアプリケーションでこれを非常に広範囲に実行しました。このアプリケーションには、単一のMySQLインスタンスに存在するいくつかのデータベースがあります。 「現在の」データベースの各テーブルのビューを作成している限り、この方法でクロスデータベースモデル結合を実現できます。

ビューへの挿入/更新に関する限り、ユースケースでは、ビューは基本的に「select * from [db.table];」です。つまり、複雑な結合やフィルタリングは行わないため、save()からの挿入/更新トリガーは問題なく機能します。ユースケースでこのような複雑な結合や広範なフィルタリングが必要な場合、読み取り専用のシナリオでは問題はないと思われますが、挿入/更新の問題が発生する可能性があります。 MySQLには、クロステーブル、複雑なフィルターなどを含むビューへの更新を妨げる基本的な制約があると思います。

とにかく、MySQL以外のRDBMSを使用している場合、走行距離は異なる場合がありますが、Djangoは物理的なテーブルまたはビューの上にあるかどうかはあまり気にしません。期待どおりに実際に機能するかどうかを決定するのはRDBMSになります。前のコメント者が述べたように、syncdbをウィンドウの外に投げる可能性がありますが、Djangoによって作成された物理テーブルをドロップし、 "create view"を実行するpost-syncdb信号で問題を回避しました。 .. "コマンド。ただし、post-syncdbシグナルは、トリガーされる方法が少し難解なので、そこにも注意が必要です。

編集:もちろん「post-syncdbシグナル」では「post-syncdbリスナー」を意味します

3
Joe Holloway

Django Official Documentation から、次のようにビューを呼び出すことができます。

#import library
from Django.db import connection

#Create the cursor
cursor = connection.cursor()

#Write the SQL code
sql_string = 'SELECT * FROM myview'

#Execute the SQL
cursor.execute(sql_string)
result = cursor.fetchall()

それが役に立てば幸い ;-)

3
jobima