Det finns en lösning för Django 1.6+ (inklusive 1.11) för MySQL och sqlite backends, genom alternativ ForeignKey. db_constraint =False
och explicit Meta.db_table
. Om databasnamnet och tabellnamnet är citerade av ' ` ' (för MySQL) eller av ' " ' (för annan db), t.ex. db_table = '"db2"."table2"'
). Då citeras det inte mer och pricken är ur citat. Giltiga frågor sammanställs av Django ORM. En bättre liknande lösning är db_table = 'db2"."table2'
(som inte bara tillåter anslutningar utan det är också av en fråga närmare migrering av db-begränsningar)
db2_name = settings.DATABASES['db2']['NAME']
class Table1(models.Model):
fk = models.ForeignKey('Table2', on_delete=models.DO_NOTHING, db_constraint=False)
class Table2(models.Model):
name = models.CharField(max_length=10)
....
class Meta:
db_table = '`%s`.`table2`' % db2_name # for MySQL
# db_table = '"db2"."table2"' # for all other backends
managed = False
Frågeuppsättning:
>>> qs = Table2.objects.all()
>>> str(qs.query)
'SELECT "DB2"."table2"."id" FROM DB2"."table2"'
>>> qs = Table1.objects.filter(fk__name='B')
>>> str(qs.query)
SELECT "app_table1"."id"
FROM "app_table1"
INNER JOIN "db2"."app_table2" ON ( "app_table1"."fk_id" = "db2"."app_table2"."id" )
WHERE "db2"."app_table2"."b" = 'B'
Den frågetolkningen stöds av alla db-backends i Django måste dock andra nödvändiga steg diskuteras individuellt av backends. Jag försöker svara mer allmänt eftersom jag hittade en liknande viktig fråga .
Alternativet 'db_constraint' är nödvändigt för migrering, eftersom Django inte kan skapa referensintegritetsbegränsningenADD foreign key table1(fk_id) REFERENCES db2.table2(id)
,
men den kan skapas manuellt
för MySQL.
En fråga för särskilda backends är om en annan databas kan anslutas till standarden vid körning och om en främmande nyckel för flera databaser stöds. Dessa modeller är också skrivbara. Den indirekt anslutna databasen ska användas som en äldre databas med managed=False
(eftersom bara en tabell django_migrations
för migrationer skapas spårning endast i den direktanslutna databasen. Denna tabell ska endast beskriva tabeller i samma databas.) Index för främmande nycklar kan dock skapas automatiskt på den hanterade sidan om databassystemet stöder sådana index.
Sqlite3 :Den måste kopplas till en annan standard sqlite3-databas vid körning (svar SQLite - Hur sammanfogar du tabeller från olika databaser ), i bästa fall genom signalen connection_created :
from django.db.backends.signals import connection_created
def signal_handler(sender, connection, **kwargs):
if connection.alias == 'default' and connection.vendor == 'sqlite':
cur = connection.cursor()
cur.execute("attach '%s' as db2" % db2_name)
# cur.execute("PRAGMA foreign_keys = ON") # optional
connection_created.connect(signal_handler)
Då behöver den inte en databasrouter förstås och en vanlig django...ForeignKey
kan användas med db_constraint=False. En fördel är att "db_table" inte behövs om tabellnamnen är unika mellan databaser.
I MySQL främmande nycklar mellan olika databaser är lätta. Alla kommandon som SELECT, INSERT, DELETE stöder alla databasnamn utan att bifoga dem tidigare.
Den här frågan handlade om äldre databaser. Jag har dock några intressanta resultat även med migrationer.