Django eine App ein Modell mehrere Datenbanken

Ich bin neu bei django webapp Entwicklung und ich bin mit einem Problem fest. Ich habe 1 App mit 1 Modell erstellt, um Daten mit 1 Formular in die Datenbank einzufügen. Ich werde hierfür mehrere Datenbanken nutzen. Jede Datenbank hat 1 Tabelle (für jetzt) ​​mit der gleichen Struktur. Jetzt ist mein Problem:

Wie kann ich nur 1 Modell, 1 Ansicht und 1 Formular für mehrere Datenbanken und deren Tabellen verwenden. Datenbanken und Tabellen sollten eingeschaltet werden, um ihre jeweiligen URLs anzurufen.

ZB http://www.example.com/x/abc/ wird auf die erste Datenbank zugreifen und es sind Tabellen für alle Operationen.
Http://www.example.com/y/abc/ wird auf die zweite Datenbank zugreifen

Ich habe bereits versucht, die Probe db Routing in django Dokumentation zur Verfügung gestellt, aber es hilft nicht viel. Auch ich konnte nicht finden, eine relative post / Frage, die dieses Problem betrifft

Ich möchte dies tun, weil ich später noch mehr Modelle und Formulare für den Zugriff auf die Daten aus den Datenbanktabellen hinzufügen werde und das scheint mir der sauberste Weg zu sein

PS: Ich verwende django 1.9.6

2 Solutions collect form web for “Django eine App ein Modell mehrere Datenbanken”

Unabhängig davon, ob dies ein guter Weg ist, um Ihre Anwendung zu architektieren, können Sie sagen, Django welche Datenbank zu lesen und zu schreiben mit mit :

Person.objects.using('db1').create(...) Person.objects.using('db2').create(...) 

Sie brauchen also keinen Router zu verwenden, einfach die beiden Datenbanken in Ihren Einstellungen zu definieren und die Migration auf beiden zu starten. Die Tabelle Ihres Modells wird in jeder Datenbank erstellt und in Ihrem Code können Sie aus der beiden Datenbank lesen und schreiben, basierend auf einer beliebigen Logik (zB basierend auf dem Anforderungspfad).

Siehe https://docs.djangoproject.com/de/1.9/topics/db/multi-db/#manually-selecting-a-database

Ich reagiere wegen deines "Ich frage mich, ob es noch eine andere Lösung gibt". Es gibt. Ich habe es auf und läuft auf einer Website … mehrere SQLite-Datenbanken mit einer App. Sie haben auch db Router Probleme, die ich auch mit kämpfte.

Zuerst stelle irgendwo eine router.py Datei ein, die folgendes enthält:

 class Router(object): appname = '' def db_for_read(self, model, **hints): """ Attempts to read self.appname models go to model.db. """ if model._meta.app_label == self.appname: return model.db return None def db_for_write(self, model, **hints): """ Attempts to write self.appname models go to model.db. """ if model._meta.app_label == self.appname: return model.db return None def allow_relation(self, obj1, obj2, **hints): """ Allow relations if a model in the self.appname app is involved. """ if obj1._meta.app_label == self.appname or \ obj2._meta.app_label == self.appname: return True return None # This is possibly the new way, for beyond 1.8. ''' def allow_migrate(self, db, app_label, model_name=None, **hints): """ Make sure the self.appname app only appears in the self.appname database. """ if app_label == self.appname: return db == self.appname return None ''' # Contrary to Djano docs this one works with 1.8, not the one above. def allow_migrate(self, db, model): """ Make sure the self.appname app only appears in the self.appname database. """ if db == self.appname: return model._meta.app_label == self.appname elif model._meta.app_label == self.appname: return False return None 

Ich habe das nur mit Django 1.8 getestet; Wie Sie mit 1.9 verwenden, werden Sie, nach den docs zumindest, die andere allow_migrate .

Beachten Sie insbesondere, dass: (1) es gibt keine squirrely Basisklassen zu Router () mit Attributen, was bedeutet, dass die Python- type Funktion kann leicht verwendet werden, um es zu klonen; Und (2) offensichtlich ist die aktuelle Modellinstanz innerhalb Router() über einen äußeren Namensraum zugänglich.

Also jetzt, in deinem models.py , mach das:

 from django.db import models import os appname = os.path.dirname(__file__).split('/')[-1] from dirwhereyouputtherouter.router import Router router = type( appname, (Router,), dict(appname=appname) ) class Book(models.Model): # This is the default, for use when there is only one db per app. db = appname # the various fields here, etc. 

Machen Sie das für jedes Modell. Und dann wird der Router() wenn er mit einer Abfrage getroffen wird return model.db . Ich wähle hier, in meinem Schema, um das Standard-Django-Schema zu behalten … von der App, die es den Namen aus dem Namen seines Verzeichnisses erhält.

Nun, in settings.py , brauchst du DATABASE_ROUTERS = [ 'appdir.models.router', ] . Das leitet die Abfrage über den router , den wir in models.py mit der Funktion type() initialisiert haben. Beachten Sie insbesondere, dass ich hier nicht die default in DATABASE_ROUTERS . Ich habe eine, die in der DATABASES Einstellung mit default als Schlüssel aufgeführt ist. Wenn Sie Ihre anfänglichen Migrationen durchführen, werden die verschiedenen Django-Apps-Tabellen in der default Datenbank enden, standardmäßig, da der Router() beiseite tritt.

Also in deiner Ansicht würdest du mit Book.db = x , wo die View-Signatur myview(request, x, someothername): Es gibt eine Chance, dass du den ganzen View-Körper mit einem try: finally: drapieren willst try: finally: wo im finally Block würdest du die Auswahl der Datenbank auf einen gewissen Standard zurücksetzen.

Ich muss gestehen, dass es in der Salbe eine Fliege geben kann, wenn es um Migrationen geht. Ich hasse diese, und in meinem Fall schreibe ich über den gesamten Inhalt meiner kleinen SQLite-Datenbanken, wann immer ich sie aktualisiere, was häufig ist. Also, es geht nicht darum, Daten zu speichern, ich werfe sie und die Migrations-Ordner weg, wann immer ich Änderungen vornehmen muss. Aber wenn deine Umstände anders sind, musst du mit den migrate und makemigrations Befehlen makemigrations . Jede meiner Datenbanken hat das gleiche Schema, wie es das Modell definiert. Also habe ich eigentlich eine leere Datenbank erstellt, indem ich vorübergehend einen Eintrag in die DATABASES Einstellung legte, die als Schlüssel den Namen der App hatte. Ich habe das benutzt, um eine Kopie der SQLite-db-Datei zu erstellen und sie dann einfach zu kopieren und umbenannt zu werden, wenn ich eine neue Datenbank hinzufügen wollte (indem ich die Details für die neue Datenbank auf DATENBANKEN führe und den temporären Eintrag lösche, der den Appname als Schlüssel hatte ). Alternativ können Sie die Datenbank beibehalten und gut nutzen, deren Schlüssel in DATABASES der Name der App ist.

Aber leider sind wir nicht fertig. Ich musste admin.py reparieren Nach dem Erstellen in admin.py class BookAdmin(admin.ModelAdmin): in der üblichen Weise finden Sie nicht Ihre beiden Datenbanken in admin zugänglich. So sieht mein admin.py aus wie:

 from django.contrib import admin from django.conf import settings import os class BookAdmin(admin.ModelAdmin): list_display = ... list_filter = ... etc. from models import Book appname = os.path.dirname(__file__).split('/')[-1] dbkeys = settings.DATABASES.keys() while 'default' in dbkeys: dbkeys.remove('default') dbkeys = [ k for k in dbkeys if os.path.dirname(settings.DATABASES[k]['NAME']).split(os.sep)[-1] == appname ] for dbname in dbkeys: if dbname == dbkeys[0]: class Book_(Book): class Meta: proxy = True verbose_name = Book.__name__ + '_' + ''.join('_' + x.capitalize() or '_' for x in dbname.split('_')) verbose_name_plural = Book.__name__ + 's_'+ ''.join('_' + x.capitalize() or '_' for x in dbname.split('_')) db_table = appname + '_book' Book_.db = dbname Book_.__name__ = Book.__name__ + '_' + appname.capitalize() + '_' + ''.join('_' + x.capitalize() or '_' for x in dbname.split('_')) admin.site.register(Book_, BookAdmin) elif dbname == dbkeys[1]: class Book__(Book): class Meta: proxy = True verbose_name = Book.__name__ + '_' + ''.join('_' + x.capitalize() or '_' for x in dbname.split('_')) verbose_name_plural = Book.__name__ + 's_'+ ''.join('_' + x.capitalize() or '_' for x in dbname.split('_')) db_table = appname + '_book' Book__.db = dbname Book__.__name__ = Book.__name__ + '_' + appname.capitalize() + '_' + ''.join('_' + x.capitalize() or '_' for x in dbname.split('_')) admin.site.register(Book__, BookAdmin) 

Dies funktioniert, weil ich die db-Dateien für jede app in der App-Ordner. Tut mir leid, dass es alles ein bisschen knifflig ist. Ich hatte gute Gründe, die Fähigkeit zu haben. Siehe auch meine unbeantwortete Frage nach Unterklassungsmodellen, um sie mit admin.site.register hier zu registrieren.

  • Mac + virtualenv + pip + postgresql = Fehler: pg_config ausführbare Datei nicht gefunden
  • Füllen Many2many field (odoo 8)
  • Schalte eine Warnung in der sqlalchemy aus
  • Wie kann ich Aktualisierungs- / Ersetzungsoperationen in PostgreSQL beschleunigen?
  • Hinzufügen einer Benutzer / Konten-Tabelle zu Postgres in Django View
  • Speichern von hochgeladenen Fotos und Dokumenten - Dateisystem vs Datenbank-Blob
  • SQLAlchemy: update from_select
  • Python, um HTML-Daten zu analysieren und in die Datenbank zu speichern
  • Bereitstellen von Django zu Heroku (Psycopg2-Fehler)
  • Django JSONField in ArrayField
  • Vermeidung von Rennbedingungen, Django + Heroku + PostgreSQL
  • Python ist die beste Programmiersprache der Welt.