Съществува решение за Django 1.6+ (включително 1.11) за MySQL и sqlite backends, чрез опция ForeignKey. db_constraint =False
и изрично Meta.db_table
. Ако името на базата данни и името на таблицата са в кавички от ' ' (за MySQL) или от ' " ' (за други db), напр. db_table = '"db2"."table2"'
). Тогава не се цитира повече и точката е извън цитирането. Валидни заявки се компилират от Django ORM. По-добро подобно решение е db_table = 'db2"."table2'
(което позволява не само присъединяване, но и с един проблем е по-близо до преминаване на миграция на ограничение на 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
Набор от заявки:
>>> 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'
Този анализ на заявка се поддържа от всички сървъри на db в Django, обаче другите необходими стъпки трябва да бъдат обсъдени индивидуално от бекендовете. Опитвам се да отговоря по-общо, защото намерих подобен важен въпрос .
Опцията 'db_constraint' е необходима за миграции, тъй като Django не може да създаде ограничението за целостта на препраткатаADD foreign key table1(fk_id) REFERENCES db2.table2(id)
,
но може да се създаде ръчно
за MySQL.
Въпросът за конкретни бекендове е дали друга база данни може да бъде свързана към по подразбиране по време на изпълнение и дали се поддържа външен ключ за кръстосана база данни. Тези модели също са с възможност за запис. Непряко свързаната база данни трябва да се използва като наследена база данни с managed=False
(защото само една таблица django_migrations
за проследяване на миграциите се създава само в пряко свързаната база данни. Тази таблица трябва да описва само таблици в една и съща база данни.) Индексите за външни ключове обаче могат да се създават автоматично от управляваната страна, ако системата на базата данни поддържа такива индекси.
Sqlite3 :Трябва да бъде прикачен към друга база данни sqlite3 по подразбиране по време на изпълнение (отговор SQLite – Как да обединявате таблици от различни бази данни ), в най-добрия случай от сигнала 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)
Тогава няма нужда от рутер за база данни разбира се и нормален django...ForeignKey
може да се използва с db_constraint=False. Предимство е, че "db_table" не е необходимо, ако имената на таблиците са уникални между базите данни.
В MySQL външни ключове между различни бази данни са лесни. Всички команди като SELECT, INSERT, DELETE поддържат всякакви имена на база данни, без да ги прикачват преди това.
Този въпрос беше за наследени бази данни. Имам обаче някои интересни резултати и с миграциите.