Django ORM, использующий внешнюю базу данных для неуправляемой модели в представлении, говорит, что отношение не существует

У меня есть два подключения к базе данных Postgres, и при использовании другого соединения, чем по умолчанию, вызовы ORM не работают на представлениях, но не на raw. Я использую docker, контейнеры подключены и используют собственную команду Django runserver. Использование ORM в django command или django shell работает нормально, но не в представлении.

В качестве примечания, обе базы данных на самом деле являются Django-проектами, но основной проект считывает некоторые данные непосредственно из базы данных другого проекта, используя собственную неуправляемую модель.

  • Python: 3.9.7
  • Django: 3.2.10
  • Postgres: 13.3 (основной проект), 12.2 (побочный проект)
# settings
DATABASES = {
    'default': {
        'ENGINE':       'django.db.backends.postgresql',
        'USER':         'pguser',
        'PASSWORD':     'pguser',
        'NAME':         'mainproject',
        'HOST':         'project-db', # docker container
        'PORT':         '5432',
    },
    'external': {
        'ENGINE':       'django.db.backends.postgresql',
        'USER':         'pguser',
        'PASSWORD':     'pguser',
        'NAME':         'sideproject',
        'HOST':         'side-db', # docker container, attached to same network
        'PORT':         '5432',
    },
}

# My unmanaged model
class MyTestModel(models.Model):
​
    class Meta:
        # table does not exist in 'default', but it does exist in 'external'
        db_table = 'my_data_table' 
        managed = False

        # my_data_table is very simple it has id field as integer
        # and primary key (works out of the box with django)
        # it has normal fields only like IntegerField or CharField
        # But even if this model is empty then it returns normally the PK field


# My custom command in Main project
# python manage.py mycommand
# ...
def handle(self, *args, **options):

    # This works fine and data from external is populated in MyTestModel
    data = MyTestModel.objects.using('external').all()
    for x in data:
        print(x, vars(x))


# My simple view in Main project

class MyView(TemplateView):

    # But using example in views.py, random view class:
    def get(self, request, *args, **kwargs):

        # with raw works
        data = MyTestModel.objects.using('external').raw('select * from my_data_table')
        for x in data:
            print(x, vars(x))

        # This does not work
        # throws ProgrammingError: relation "my_data_table" does not exist
        data = MyTestModel.objects.using('external').all()
        for x in data:
            print(x, vars(x))

        return super().get(request, *args, **kwargs)    

Почему-то runserver и views не генерирует запрос корректно при использовании ORM. Это не может быть ошибкой соединения, потому что при запуске команды или представления с ".raw()" все работает.

Теперь забавная вещь: если я изменю "db_table" на что-то общее для обеих баз данных, скажем, на "django_content_type", ORM "filter()" и "all()" работают и в представлении. И да, тогда он действительно возвращает данные из правильной базы данных. Так, если основной проект имеет 50 типов контента, а побочный проект (внешний) имеет 100 типов контента, он фактически возвращает эти 100 типов контента из внешнего.

Я перепробовал все, перестраивая docker, создавая новые таблицы в базе данных напрямую, принудительно перезагружая пользователя postgres и убедившись, что все разрешения владельца и все разрешения (должны быть в порядке в любом случае, потому что командная сторона работает). Я даже пытался использовать другую базу данных.

Я знаю, что не опубликовал полные настройки и мои локальные настройки, которые могли бы больше помочь в решении этого дела.

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

Вернуться на верх