Доступ к указанной базе данных в команде миграции django внутри маршрутизатора базы данных - PullRequest
0 голосов
/ 08 мая 2018

Используя Django 1.11, я пытаюсь создать собственный маршрутизатор для выбора базы данных на основе используемого URL.

Например, если URL-адрес customer1.example.com, я хочу выбрать базу данных customer1, и аналогичным образом, если это customer2.example.com, я хочу выбрать базу данных customer2

.

Моя текущая настройка отлично работает! Одна проблема - когда я пытаюсь запустить миграцию (или другие команды, зависящие от базы данных), происходит сбой - даже если я указываю базу данных, используя параметр --database, например python manage.py migrate --database customer1

Я не уверен, что делать, поскольку для них нет запроса - я хочу на самом деле вернуть точное имя, указанное в командной строке (например, customer1). Но это не намеки, ни какие-либо другие варианты. Как получить доступ к параметру командной строки, который использовался для запуска команды? Иначе мне нечего возвращать!

Это мои настройки:

settings.py:

# Database to connect to
DATABASES = {
  'default': {},
  'customer1': {
    'ENGINE': 'django.db.backends.oracle',
    'NAME': 'xxxx',
    'USER': 'yyyy',
    'PASSWORD': 'zzzz',
    'HOST': '192.168.168.176',
    'PORT': '1521',
  },
  'customer2': {  
    'ENGINE': 'django.db.backends.oracle',
    'NAME': 'xxxx',
    'USER': 'yyyy',
    'PASSWORD': 'zzzz',
    'HOST': '192.168.168.179',
    'PORT': '1521',
  }
}

# Specify custom router
DATABASE_ROUTERS = ['workflow.router.RequestDatabaseRouter']

router.py (пользовательский маршрутизатор, использующий поток для получения текущего объекта запроса)

from mainapp.threads import get_current_request

class RequestDatabaseRouter(object):
  def db_for_read(self, model, **hints):
    try:
      request = get_current_request()
      return request.META['HTTP_HOST'].split(':', 1)[0].split('.',1)[0]
    except:
      # ??????

  def db_for_write(self, model, **hints):
    try:
      request = get_current_request()
      return request.META['HTTP_HOST'].split(':', 1)[0].split('.',1)[0]
    except:
      # ??????

  def allow_relation(self, obj1, obj2, **hints):
    return True

  def allow_migrate(self, db, app_label, model_name=None, **hints):
    return True

Мне кажется, что в блоке исключений должно быть что-то, что просто возвращает "независимо от того, какая опция --database была в команде" - но я не смог найти способ получить к этому доступ. Любой совет?

Вот вывод, когда я пытаюсь выполнить команду: python manage.py migrate --database=customer1

Operations to perform:
  Apply all migrations: MOC, admin, auth, contenttypes, frontend, sessions, sites, viewflow
Running migrations:
  No migrations to apply.
Traceback (most recent call last):
  File "manage.py", line 22, in <module>
    execute_from_command_line(sys.argv)
  File "/mnt/c/cygwin64/home/chrisb/smart/python/MOC/lib/python3.5/site-packages/django/core/management/__init__.py", line 364, in execute_from_command_line
    utility.execute()
  File "/mnt/c/cygwin64/home/chrisb/smart/python/MOC/lib/python3.5/site-packages/django/core/management/__init__.py", line 356, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "/mnt/c/cygwin64/home/chrisb/smart/python/MOC/lib/python3.5/site-packages/django/core/management/base.py", line 283, in run_from_argv
    self.execute(*args, **cmd_options)
  File "/mnt/c/cygwin64/home/chrisb/smart/python/MOC/lib/python3.5/site-packages/django/core/management/base.py", line 330, in execute
    output = self.handle(*args, **options)
  File "/mnt/c/cygwin64/home/chrisb/smart/python/MOC/lib/python3.5/site-packages/django/core/management/commands/migrate.py", line 227, in handle
    self.verbosity, self.interactive, connection.alias, apps=post_migrate_apps, plan=plan,
  File "/mnt/c/cygwin64/home/chrisb/smart/python/MOC/lib/python3.5/site-packages/django/core/management/sql.py", line 53, in emit_post_migrate_signal
    **kwargs
  File "/mnt/c/cygwin64/home/chrisb/smart/python/MOC/lib/python3.5/site-packages/django/dispatch/dispatcher.py", line 193, in send
    for receiver in self._live_receivers(sender)
  File "/mnt/c/cygwin64/home/chrisb/smart/python/MOC/lib/python3.5/site-packages/django/dispatch/dispatcher.py", line 193, in <listcomp>
    for receiver in self._live_receivers(sender)
  File "/mnt/c/cygwin64/home/chrisb/smart/python/MOC/MOC/material/frontend/apps.py", line 158, in update_modules
    _, created = DbModule.objects.get_or_create(label=module.label)
  File "/mnt/c/cygwin64/home/chrisb/smart/python/MOC/lib/python3.5/site-packages/django/db/models/manager.py", line 85, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
  File "/mnt/c/cygwin64/home/chrisb/smart/python/MOC/lib/python3.5/site-packages/django/db/models/query.py", line 464, in get_or_create
    return self.get(**lookup), False
  File "/mnt/c/cygwin64/home/chrisb/smart/python/MOC/lib/python3.5/site-packages/django/db/models/query.py", line 374, in get
    num = len(clone)
  File "/mnt/c/cygwin64/home/chrisb/smart/python/MOC/lib/python3.5/site-packages/django/db/models/query.py", line 232, in __len__
    self._fetch_all()
  File "/mnt/c/cygwin64/home/chrisb/smart/python/MOC/lib/python3.5/site-packages/django/db/models/query.py", line 1118, in _fetch_all
    self._result_cache = list(self._iterable_class(self))
  File "/mnt/c/cygwin64/home/chrisb/smart/python/MOC/lib/python3.5/site-packages/django/db/models/query.py", line 53, in __iter__
    results = compiler.execute_sql(chunked_fetch=self.chunked_fetch)
  File "/mnt/c/cygwin64/home/chrisb/smart/python/MOC/lib/python3.5/site-packages/django/db/models/sql/compiler.py", line 876, in execute_sql
    sql, params = self.as_sql()
  File "/mnt/c/cygwin64/home/chrisb/smart/python/MOC/lib/python3.5/site-packages/django/db/models/sql/compiler.py", line 428, in as_sql
    extra_select, order_by, group_by = self.pre_sql_setup()
  File "/mnt/c/cygwin64/home/chrisb/smart/python/MOC/lib/python3.5/site-packages/django/db/models/sql/compiler.py", line 46, in pre_sql_setup
    self.setup_query()
  File "/mnt/c/cygwin64/home/chrisb/smart/python/MOC/lib/python3.5/site-packages/django/db/models/sql/compiler.py", line 37, in setup_query
    self.select, self.klass_info, self.annotation_col_map = self.get_select()
  File "/mnt/c/cygwin64/home/chrisb/smart/python/MOC/lib/python3.5/site-packages/django/db/models/sql/compiler.py", line 227, in get_select
    sql, params = self.compile(col, select_format=True)
  File "/mnt/c/cygwin64/home/chrisb/smart/python/MOC/lib/python3.5/site-packages/django/db/models/sql/compiler.py", line 373, in compile
    sql, params = node.as_sql(self, self.connection)
  File "/mnt/c/cygwin64/home/chrisb/smart/python/MOC/lib/python3.5/site-packages/django/db/models/expressions.py", line 695, in as_sql
    return "%s.%s" % (qn(self.alias), qn(self.target.column)), []
  File "/mnt/c/cygwin64/home/chrisb/smart/python/MOC/lib/python3.5/site-packages/django/db/models/sql/compiler.py", line 364, in quote_name_unless_alias
    r = self.connection.ops.quote_name(name)
  File "/mnt/c/cygwin64/home/chrisb/smart/python/MOC/lib/python3.5/site-packages/django/db/backends/dummy/base.py", line 20, in complain
    raise ImproperlyConfigured("settings.DATABASES is improperly configured. "
django.core.exceptions.ImproperlyConfigured: settings.DATABASES is improperly configured. Please supply the ENGINE value. Check settings documentation for more details.

Результаты `manage.py migrate --database customer1:

{'customer1': {'PASSWORD': 'xxx', 'HOST': '192.168.168.176', 'NAME': 'mclaren', 'ENGINE': 'django.db.backends.oracle', 'PORT': '1521', 'USER': 'xxx'}, 'customer2': {'PASSWORD': 'xxx', 'HOST': '192.168.168.179', 'NAME': 'mclaren', 'ENGINE': 'django.db.backends.oracle', 'PORT': '1521', 'USER': 'xxx'}, 'default': {'PASSWORD': '', 'HOST': '', 'NAME': '', 'TIME_ZONE': None, 'USER': '', 'AUTOCOMMIT': True, 'CONN_MAX_AGE': 0, 'OPTIONS': {}, 'PORT': '', 'TEST': {'CHARSET': None, 'MIRROR': None, 'NAME': None, 'COLLATION': None}, 'ENGINE': 'django.db.backends.dummy', 'ATOMIC_REQUESTS': False}}

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

1 Ответ

0 голосов
/ 08 мая 2018

Обратите внимание на эти строки в трассировке стека:

 File "/mnt/c/cygwin64/home/chrisb/smart/python/MOC/lib/python3.5/site-packages/django/core/management/commands/migrate.py", line 227, in handle
    self.verbosity, self.interactive, connection.alias, apps=post_migrate_apps, plan=plan,
  File "/mnt/c/cygwin64/home/chrisb/smart/python/MOC/lib/python3.5/site-packages/django/core/management/sql.py", line 53, in emit_post_migrate_signal
    **kwargs
  File "/mnt/c/cygwin64/home/chrisb/smart/python/MOC/lib/python3.5/site-packages/django/dispatch/dispatcher.py", line 193, in send
    for receiver in self._live_receivers(sender)
  File "/mnt/c/cygwin64/home/chrisb/smart/python/MOC/lib/python3.5/site-packages/django/dispatch/dispatcher.py", line 193, in <listcomp>
    for receiver in self._live_receivers(sender)
  File "/mnt/c/cygwin64/home/chrisb/smart/python/MOC/MOC/material/frontend/apps.py", line 158, in update_modules
    _, created = DbModule.objects.get_or_create(label=module.label)

Очевидно, есть сигнал post_migrate, пытающийся создать экземпляр DbModule с использованием settings.DATBASE['default'] conf.

Что вызвало django.core.exceptions.ImproperlyConfigured.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...