it-swarm.com.de

Django- und Postgresql-Schemata

Ich habe die ganze Woche versucht, dieses Problem zu lösen, sehr geschätzt.

Ich habe verschiedene Schemas in einer Postgres-Datenbank und ich möchte in der Lage sein, sie innerhalb derselben oder über verschiedene Django-Apps hinweg abzubilden.

Einige der Schemata sind:

proben

ausgrabung

geophysik

...

Ich habe die empfohlene Methode ausprobiert, bekomme aber keine Daten aus den Schemas, sondern kann nur mit verwalteten Tabellen eine Verbindung zum öffentlichen Schema herstellen. Hier sind die Datenbankverbindungen aus der Datei 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',
},
}

quelle: https://www.amvtek.com/blog/posts/2014/Jun/13/accessing-multiple-postgres-schemas-von-Django/

In der model.py füge ich hinzu:

    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'

Ich möchte die Schemas nicht auf Benutzer beschränken, und die Datenbank wurde vor einigen Jahren erstellt, daher darf ich nicht alles unter ein Schema stellen. Ich weiß, es gibt verschiedene Lösungen für stackoverflow und andere Corener des Internets. Ich habe diese probiert, aber ich kann das nicht zum Laufen bringen. Irgendwelche Ideen, wie man dieses löst?

5
Gary Nobles

Da Django Postgres-Datenbankschemata nicht standardmäßig unterstützt, verwenden Sie einen Datenbank-Router , um dies zu gewährleisten. 

Ich habe eine Testdatenbank erstellt, um dies auszuprobieren. So reproduzieren Sie sie:

Erstellen Sie eine Testdatenbank mit 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
);

Fügen Sie den Einstellungen die Schemas als verschiedene Datenbankverbindungen hinzu. Denken Sie daran, Host hinzuzufügen, um den Fehler "Peer-Authentifizierung fehlgeschlagen" zu vermeiden.

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'
},

}

Als Nächstes erstellen Sie das Modell 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'

Erstellen Sie einen Datenbankrouter, um alle beispielbezogenen Abfragen an die Beispieldatenbank weiterzuleiten:

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

Grundsätzlich leitet der Router alle in ROUTED_MODELS angegebenen Modelle an die Datenbankverbindung samples und gibt für alle anderen Modelle None zurück. Dadurch werden sie an die default-Datenbankverbindung weitergeleitet.

Fügen Sie schließlich den Router zu Ihren settings.py hinzu

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

Wenn Sie nun eine Abfrage für das Modell MySample durchführen, werden Daten aus dem Schema samples abgerufen.

7
tarikki

Ich habe diese Quelle auch konsultiert, konnte sie aber nicht wie Sie lösen, aber durch Tests habe ich Folgendes erreicht.

Wenn wir zum Beispiel die Schemas foo und bar haben, schreiben Sie in der 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'

Dann können wir jedes Modell auf das gewünschte Schema umleiten, sofern die Variable in True verwaltet wird. Die Einschränkung ist, dass wir die Tabelle selbst benennen müssen.