在数据库路由器内部的迁移命令django中访问指定的数据库

Accessing specified database in migrate command django inside database router

使用 Django 1.11,我正在尝试创建一个自定义路由器,以根据使用的 URL 选择一个数据库。

例如,如果 URL 是 customer1.example.com,我想选择数据库 'customer1',同样如果它是 customer2.example.com,我希望它选择数据库 'customer2'

我当前的设置效果很好!一个问题 - 当我尝试 运行 迁移(或其他依赖数据库的命令)时,它会失败 - 即使我使用 --database 选项指定数据库,例如 python manage.py migrate --database customer1

我不确定该怎么做,因为没有这些要求 - 我实际上想 return 在命令行中指定的确切名称(例如 customer1)。但它不是提示,也不是任何其他选项。如何访问用于 运行 命令的命令行选项?不然我也没什么好return!

这是我的设置:

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

我觉得 returns "whatever the --database option was in the command" 的 except 块中应该有一些东西 - 但我找不到访问它的方法。有什么建议吗?

这是我尝试 运行 命令时的输出: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}}

命令仍然完全按照我上面的描述失败。我已经看到默认数据库在站点 运行ning 时自动填充,但它似乎忽略了我输入的任何密码。也许路由器需要一些调整,但我不知道如何处理它。

注意堆栈跟踪中的这些行:

 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 信号试图使用 settings.DATBASE['default'] conf 创建一个 DbModule 实例。

这导致了 django.core.exceptions.ImproperlyConfigured