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 из установленных приложений и удаление его промежуточного ПО устранило проблему.