Подтвердить что ты не робот

Получение данных из нескольких баз данных с одинаковыми именами таблиц в 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
4b9b3361

Ответ 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