web-dev-qa-db-ja.com

Djangoおよびpostgresqlスキーマ

私はこれを一週間ずっと解決しようとしてきましたが、とても感謝しています。

Postgres dbにはさまざまなスキーマがあり、同じアプリ内または異なるDjango=アプリから)からそれらにマッピングできるようにしたいと思います。

スキーマの一部は次のとおりです。

サンプル

発掘

地球物理学

...

推奨される方法を試しましたが、スキーマから表示するデータを取得できません。管理されたテーブルを使用してパブリックスキーマにのみ接続できます。これはsettings.pyファイルからのデータベース接続です。

DATABASES = {

'default': {
        'ENGINE': 'Django.db.backends.postgresql_psycopg2',
        'OPTIONS': {
            'options': '-c search_path=Django,public'
        },
        'NAME': 'gygaia',
        'USER': 'appuser',
        'PASSWORD': 'secret',
},

'samples': {
        'ENGINE': 'Django.db.backends.postgresql_psycopg2',
        'OPTIONS': {
            'options': '-c search_path=samples,public'
        },
        'NAME': 'gygaia',
        'USER': 'appuser',
        'PASSWORD': 'secret',
},
}

ソース: https://www.amvtek.com/blog/posts/2014/Jun/13/accessing-multiple-postgres-schemas-from-Django/

Model.pyに次を追加します。

    from Django.db import models

    # Create your models here.
    class Storage(models.Model):
        #id = models.IntegerField(default=0)
        storage_id = models.AutoField(primary_key=True)
        store_name = models.CharField(max_length=200, default='')
        address_1 = models.CharField(max_length=200, default='')
        address_2 = models.CharField(max_length=200, default='')
        region = models.CharField(max_length=200, default='')
        city = models.CharField(max_length=200, default='')
        Zip = models.CharField(max_length=200, default='')
        country = models.CharField(max_length=200, default="Turkey")
        user = models.CharField(max_length=200, default="Gygaia")
        datestamp = models.DateTimeField(auto_now=True)

    class Meta():
        managed=False
        db_table = 'samples\".\"store'

スキーマをユーザーに制限したくはありません。データベースは数年前に作成されたため、すべてを1つのスキーマにまとめることはできません。 stackoverflowやその他のインターネットのコアナーに投稿されたさまざまなソリューションがあることは知っています。これらを試しましたが、これを機能させることができません。 thos oneを解決する方法はありますか?

12
Spatial Digger

DjangoはデフォルトでPostgresデータベーススキーマをサポートしていないため、これを機能させるには データベースルーター を使用します。

私はこれを試すためにテストデータベースを作成しました。それを再現する方法は次のとおりです。

Psqlでテストデータベースを作成します。

CREATE USER tester WITH PASSWORD 'lol so easy';
CREATE DATABASE multi_schema_db WITH OWNER tester;
CREATE SCHEMA samples AUTHORIZATION tester;
CREATE TABLE samples.my_samples (
  id          INTEGER   NOT NULL PRIMARY KEY,
  description CHAR(255) NOT NULL
);

スキーマを異なるデータベース接続として設定に追加します。「ピア認証に失敗しました」エラーを回避するために、Hostを追加することを忘れないでください。

DATABASES = {

'default': {
    'ENGINE': 'Django.db.backends.postgresql_psycopg2',
    'OPTIONS': {
        'options': '-c search_path=Django,public'
    },
    'NAME': 'multi_schema_db',
    'USER': 'tester',
    'PASSWORD': 'lol so easy',
    'Host': 'localhost'

},

'samples': {
    'ENGINE': 'Django.db.backends.postgresql_psycopg2',
    'OPTIONS': {
        'options': '-c search_path=samples,public'
    },
    'NAME': 'multi_schema_db',
    'USER': 'tester',
    'PASSWORD': 'lol so easy',
    'Host': 'localhost'
},

}

次にMySampleモデルを作成します。

from Django.db import models

class MySample(models.Model):
    description = models.CharField(max_length=255, null=False)

    class Meta:
        managed = False
        db_table = 'my_samples'

サンプル関連のすべてのクエリをサンプルデータベースに送信するデータベースルーターを作成します。

from database_test.models import MySample

ROUTED_MODELS = [MySample]


class MyDBRouter(object):

    def db_for_read(self, model, **hints):
        if model in ROUTED_MODELS:
            return 'samples'
        return None

    def db_for_write(self, model, **hints):
        if model in ROUTED_MODELS:
            return 'samples'
        return None

基本的に、ルーターはROUTED_MODELSで指定されたすべてのモデルをデータベース接続samplesにルーティングし、他のすべてのモデルに対してNoneを返します。これにより、defaultデータベース接続にルーティングされます。

最後に、ルーターをsettings.pyに追加します

DATABASE_ROUTERS = ('database_test.db_router.MyDBRouter',)

そして今、MySampleモデルに対してクエリを実行すると、samplesスキーマからデータをフェッチします。

13
tarikki

私もそのソースに相談しましたが、あなたのようにそれを解決することはできませんでしたが、テストを実行することで以下を達成しました。

たとえば、fooとbarというスキーマがある場合、Metaに記述します。

class MySample1 (models.Model):
     description = models.CharField (max_length = 255, null = False)
     class Goal:
         managed = True
         db_table = 'fo\".\"my_samples1'

class MySample2 (models.Model):
     description = models.CharField (max_length = 255, null = False)
     class Goal:
         managed = True
         db_table = 'bar\".\"my_samples2'

その後、変数をTrueで管理していれば、各モデルを目的のスキームにリダイレクトできます。制限は、テーブルに自分で名前を付ける必要があることです。