Внешний ключ Django в другой базе данных

У меня есть два отдельных приложения Django с двумя разными базами данных. В APP1 мне нужны все записи из одной таблицы, которая находится в базе данных APP2. Кроме того, у одной из моих моделей APP1 есть ForeignKey, который указывает на модель APP2, и, согласно документам, это невозможно.

Поскольку Django не поддерживает отношения внешнего ключа, охватывающие несколько баз данных, я не знаю, что делать.

Официальные документы:

Если вы использовали маршрутизатор для разделения моделей по разным базам данных, любой внешний ключ и отношения «многие ко многим», определяемые этими моделями, должны быть внутренними для одной базы данных.

Это связано с ссылочной целостностью. Чтобы поддерживать отношения между двумя объектами, Django необходимо знать, что первичный ключ связанного объекта действителен. Если первичный ключ хранится в отдельной базе данных, невозможно легко оценить действительность первичного ключа.

В качестве решения я подумал об объединении этих двух баз данных, чтобы эти два приложения использовали одну и ту же базу данных. Но тогда у меня был бы беспорядок с моделями, потому что APP1 нужна только одна таблица из APP2, и ему не нужны остальные модели и таблицы БД. Кроме того, я почти уверен, что это вызовет проблемы (конфликты) при переносе из этих двух приложений в одну и ту же базу данных.

Я использую маршрутизатор Django DB, и это то, что я пробовал до сих пор:

class Car(models.Model):
    _DATABASE = "cars"
    color = models.TextField(max_length=1000)
    ...

class Employee(models.Model):
    id = models.IntegerField()
    car = models.ForeignKey(Car)
    ...

Это дает мне:

django.db.utils.OperationalError: (1054, "Unknow column 'car' in 'employees'")

person Ljubisa Livac    schedule 15.06.2016    source источник


Ответы (2)


Одна БД или две?

Первый вопрос, который нужно задать себе, действительно ли необходимо иметь две разные базы данных? Несколько приложений, использующих одну и ту же базу данных, довольно распространены в мире PHP, где большинство людей используют виртуальный хостинг, а план хостинга позволяет использовать только одну базу данных.

Очень редко веб-сайт имеет достаточно трафика, чтобы разделить контент между двумя базами данных. И обычно накладные расходы маршрутизатора делают его нецелесообразным. Шардинг почти всегда лучше обрабатывается специализированным программным обеспечением.

Да должно быть два!

Это не невозможно, но просто чертовски тяжело.

Первое, что нужно сделать, это изменить свою Car модель.

class Car(models.Model):
    color = models.TextField(max_length=1000)
    class Meta:
        managed = False

Обратите внимание, что он больше не относится ко второй базе данных и неуправляем. Но у вас нет такой таблицы в вашей базе данных. Итак, вам нужно создать представление.

 CREATE OR REPLACE VIEW myapp_cars AS SELECT * FROM cars.otherapp_cars

Пожалуйста, убедитесь, что вы используете точные имена базы данных и таблиц, чтобы они соответствовали вашим существующим. Мы прошли только половину пути. Вам нужно создать триггер для вставки в другую базу данных. Это обсуждалось здесь уже много раз, поэтому я не буду вдаваться в подробности. Примеры

  1. Триггер MySQL для вставки данных в другую БД
  2. Как создать триггер для вставки данные в базу данных на другом сервере

Если вы хотите воспроизвести эти шаги, вам нужно будет добавить миграцию вручную.

person e4c5    schedule 16.06.2016
comment
Спасибо за хороший ответ! Я не знал, что несколько приложений используют одну и ту же базу данных, я подумал, что это плохая практика. Итак, поскольку вы дали мне два варианта, я буду использовать первый, он определенно более практичен. Ваше здоровье! - person Ljubisa Livac; 17.06.2016
comment
Рад, что помог в мире PHP, они обычно добавляют префикс имени приложения к таблице. например, самое популярное php-приложение wordpress, все таблицы начинаются с wp_ - person e4c5; 17.06.2016
comment
И почти забыл, что django автоматически добавляет к имени каждой таблицы префикс имени приложения. У вас возникнут проблемы только в том случае, если есть два приложения с одинаковым именем. Даже тогда настройка Meta: db_table может преодолеть это. - person e4c5; 17.06.2016

Я думаю, что эта проблема не имеет ничего общего с django. По дизайну СУБД не допускает FK между базами данных. Возможно, вы можете найти обходной путь в Интернете, но, вероятно, они не придерживаются лучших практик.

См. раздел Отношения между базами данных по адресу: https://docs.djangoproject.com/en/3.2/topics/db/multi-db/

person Alcruz    schedule 15.06.2016
comment
Я не уверен, что вы правы: stackoverflow.com/questions/3905013/ - person Ljubisa Livac; 15.06.2016
comment
Ах, простите, я думал, что это невозможно. - person Alcruz; 15.06.2016