Existuje řešení pro Django 1.6+ (včetně 1.11) pro MySQL a sqlite backends, podle možnosti ForeignKey. db_constraint =Nepravda
a explicitní Meta.db_table
. Pokud je název databáze a název tabulky uvozován pomocí ' ' ' (pro MySQL) nebo ' " ' (pro jiné db), např. db_table = '"db2"."table2"'
). Pak se více neuvozuje a tečka je mimo uvozovku. Platné dotazy sestavuje Django ORM. Lepším podobným řešením je db_table = 'db2"."table2'
(to umožňuje nejen připojení, ale je také o jeden problém blíže migraci omezení db)
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
Sada dotazů:
>>> 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'
Tato analýza dotazu je podporována všemi backendy db v Django, nicméně další nezbytné kroky musí být projednány individuálně s backendy. Snažím se odpovědět obecněji, protože jsem našel podobná důležitá otázka .
Volba 'db_constraint' je nezbytná pro migrace, protože Django nemůže vytvořit referenční integritní omezeníADD foreign key table1(fk_id) REFERENCES db2.table2(id)
,
ale lze vytvořit ručně
pro MySQL.
Otázkou u konkrétních backendů je, zda lze k výchozí databázi za běhu připojit další databázi a zda je podporován cizí klíč mezi databázemi. Tyto modely jsou také zapisovatelné. Nepřímo připojená databáze by měla být použita jako starší databáze s managed=False
(protože pouze jedna tabulka django_migrations
pro sledování migrací se vytváří pouze v přímo připojené databázi. Tato tabulka by měla popisovat pouze tabulky ve stejné databázi.) Indexy pro cizí klíče však lze na spravované straně vytvářet automaticky, pokud databázový systém takové indexy podporuje.
Sqlite3 :Musí být připojen k jiné výchozí databázi sqlite3 za běhu (odpověď SQLite – Jak spojujete tabulky z různých databází ), v nejlepším případě signálem 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)
Pak to samozřejmě nepotřebuje databázový router a normální django...ForeignKey
lze použít s db_constraint=False. Výhodou je, že "db_table" není nutné, pokud jsou názvy tabulek mezi databázemi jedinečné.
V MySQL cizí klíče mezi různými databázemi jsou snadné. Všechny příkazy jako SELECT, INSERT, DELETE podporují libovolné názvy databází bez předchozího připojení.
Tato otázka se týkala starších databází. Mám však několik zajímavých výsledků také s migrací.