Получение данных из нескольких баз данных с одинаковыми именами таблиц в django
Мне нужно получить данные из разных импортированных MySQL-баз данных в Django (Django 1.11.7, Python 3.5.2). Я запускаю manage.py inspectdb --database '<db>'
и затем использую модели в django.
До сих пор у меня был доступ только к таблицам с разными именами. Для этого я использовал ключевое слово using
в наборе запросов, чтобы указать подходящую базу данных, а затем конкатенировал результат, например так:
from ..models.db1 import Members
from ..models.db2 import Actor
context['db1_data'] = Members.objects.using('db1').filter...
context['db2_data'] = Actor.objects.using('db1').filter...
context["member_list"] = list(chain(
context["db1_data"],
context["db2_data"],
))
return context
Теперь у меня проблема в том, что в двух базах данных есть таблицы с одинаковыми названиями моделей. Я получаю следующую ошибку при использовании вышеупомянутого метода (я подставил имена):
RuntimeError: Conflicting '<table-name>' models in application '<app>': <class '<app>.<subfolder>.models.<db1>.<table-name>'> and <class '<app>.<subfolder>.models.<db2>.<table-name>'>.
Я уже пытался импортировать модель с другим именем, например так:
from ..models.db3 import Members as OtherMembers
но ошибка все еще появляется.
from..models.db1
и from..models.db2
должно быть достаточно ясно, чтобы Джанго мог определить разницу между двумя моделями?
Вероятно, одним из вариантов будет переименование самих моделей, но это будет означать переименование каждой модели базы данных с одинаковыми именами. Поскольку в будущем я буду использовать гораздо больше баз данных, это не вариант для меня.
Я пытался from models import db1, db2
а затем db1.Members
и т.д., db1.Members
все еще вызывает ошибку.
Я читал о meta db_table = 'dbname.tablename'
-option, но, поскольку модель генерируется автоматически с помощью inspectdb
, она уже имеет что-то подобное в каждом классе:
class MyModel(models.Model):
<models>
class Meta:
managed = False
db_table = 'my_model'
Как описано выше, другая база данных имеет точно такую же модель и, следовательно, те же мета-классы. Я не могу и не хочу менять каждый класс Meta.
РЕДАКТИРОВАТЬ:
Моя структура проекта выглядит так:
app
-> admin.py
-> ...
-> models.py
-> views.py
subfolder
-> models
-> db1.py
-> db2.py
-> views
-> db1.py
-> db2.py
Ответы
Ответ 1
Предполагая, что вы правильно настроили несколько баз данных:
-
Вы пытались добавить Custom Router?
Если не следовать примеру, указанному в документации.
-
Вы пытались использовать Custom Manager для своих моделей?
Создайте менеджера для каждой модели, например:
class YourModelManagerX(models.Manager):
def get_queryset(self, *args, **kwargs):
return super().get_queryset(*args, **kwargs).using('your_db_X')
Затем добавьте его в соответствующую модель в поле objects
:
class YourModel(models.Model):
...
fields
...
objects = YourManagerX()
class Meta:
managed = False
Возможно, вам придется попробовать оба сразу.
Ответ 2
Если члены db1.Members и db3.Members имеют одно и то же определение, вам не нужно повторно использовать класс Member отдельно для каждой базы данных.
Models.py
...
class Members(models.Model): # Only declared once ever!
....
то
from Models import Members
context['db1_data'] = Members.objects.using('db1').filter...
context['db3_data'] = Members.objects.using('db3').filter...
... # continue processing
Не следует ли из..models.db1 и из..models.db2 быть достаточно ясным для django, чтобы определить разницу между двумя моделями?
Модели Django не зависят от конкретной базы данных, скорее похожи на специфичные для схемы, поэтому, если у вас есть одна и та же таблица в двух разных базах данных, достаточно одного класса, расширяющего model.Models
. Затем, когда вы пытаетесь восстановить объекты, укажите либо базу данных с помощью using()
, либо используя маршрутизаторы, о которых вы можете прочитать в документах Django https://docs.djangoproject.com/en/2.0/topics/db/multi-db/#an-example