如何使用 django 从 oracle 11g 中的不同模式访问表?

How to access tables from a different schema in oracle 11g using django?

我在 oracle 11g 中有一个名为 mi_abc 的用户。 用户在数据库中没有任何 table,但可以访问另一个模式 sch_abc 中的所有 table。 当我 运行 来自 sqldeveloper 的正常 select 查询来自 mi_abc 的 sch_abc 模式时,它工作得很好,但是当我使用 django 时,我总是得到错误: -

django.db.utils.DatabaseError: ORA-00942: table or view does not exist

我尝试设置 db_table = sch_abc.tableName 并设置 db_table = tableName 但两者都给我同样的错误。知道如何解决这个问题吗?

追踪:-

Traceback (most recent call last):
  File "C:\xxx\xxx\xxx\xxx\xxx\xxx\xxxx\lib\site-packages\django\core\handlers\exception.py", line 41, in inner
    response = get_response(request)
  File "C:\xxx\xxx\xxxx\xxxx\xxxx\Python\Python37\lib\site-packages\django\utils\deprecation.py", line 142, in __call__
    response = self.process_response(request, response)
  File "C:\xxxx\xxxx\xxx\xxx\xxx\Python\Python37\lib\site-packages\django\contrib\sessions\middleware.py", line 58, in process_response
    request.session.save()
  File "C:\xxx\xxxx\xxxx\xxxx\xxxxx\Python\Python37\lib\site-packages\django\contrib\sessions\backends\db.py", line 81, in save
    return self.create()
  File "C:\xxxx\xxxxx\xxxx\xxxx\xxxxx\Python\Python37\lib\site-packages\django\contrib\sessions\backends\db.py", line 50, in create
    self._session_key = self._get_new_session_key()
  File "C:\xxxx\xxxxx\xxxxx\xxxxx\xxxx\Python\Python37\lib\site-packages\django\contrib\sessions\backends\base.py", line 164, in _get_new_session_key
    if not self.exists(session_key):
  File "C:\xxx\xxx\xxx\xxx\xxx\Python\Python37\lib\site-packages\django\contrib\sessions\backends\db.py", line 46, in exists
    return self.model.objects.filter(session_key=session_key).exists()
  File "C:\xxx\xxx\xxx\xxx\xxx\Python\Python37\lib\site-packages\django\db\models\query.py", line 673, in exists
    return self.query.has_results(using=self.db)
  File "C:\xxx\xxx\xxx\xxx\xxx\Python\Python37\lib\site-packages\django\db\models\sql\query.py", line 517, in has_results
    return compiler.has_results()
  File "C:\xxx\xxx\xxx\xxx\xxx\Python\Python37\lib\site-packages\django\db\models\sql\compiler.py", line 858, in has_results
    return bool(self.execute_sql(SINGLE))
  File "C:\xxx\xxx\xxx\xxx\xxx\Python\Python37\lib\site-packages\django\db\models\sql\compiler.py", line 899, in execute_sql
    raise original_exception
  File "C:\xxx\xxx\xxx\xxx\xxx\Python\Python37\lib\site-packages\django\db\models\sql\compiler.py", line 889, in execute_sql
    cursor.execute(sql, params)
  File "C:\xxx\xxx\xxx\xxx\xxx\Python\Python37\lib\site-packages\django\db\backends\utils.py", line 79, in execute
    return super(CursorDebugWrapper, self).execute(sql, params)
  File "C:\xxx\xxx\xxx\xxx\xxx\Python\Python37\lib\site-packages\django\db\backends\utils.py", line 64, in execute
    return self.cursor.execute(sql, params)
  File "C:\xxx\xxx\xxx\xxx\xxx\Python\Python37\lib\site-packages\django\db\utils.py", line 94, in __exit__
    six.reraise(dj_exc_type, dj_exc_value, traceback)
  File "C:\xxx\xxx\xxx\xxx\xxx\Python\Python37\lib\site-packages\django\utils\six.py", line 685, in reraise
    raise value.with_traceback(tb)
  File "C:\xxx\xxx\xxx\xxx\xxx\Python\Python37\lib\site-packages\django\db\backends\utils.py", line 64, in execute
    return self.cursor.execute(sql, params)
  File "C:\xxx\xxx\xxx\xxx\xxx\Python\Python37\lib\site-packages\django\db\backends\oracle\base.py", line 497, in execute
    return self.cursor.execute(query, self._param_generator(params))
django.db.utils.DatabaseError: ORA-00942: table or view does not exist

这绝不是官方支持的,但这在 Postgres 中有效:

class Meta:
    managed = False
    db_table = 'schema\".\"table'

对 Postgres 进行了一些试验和错误,但您可能可以对 Oracle 做一些类似的事情。这是因为 Postgres 引擎引用了对象名称,这伪造了引用机制。

更新:

在进行一些挖掘之后,我为 Oracle 找到了这个(针对 Python 3 进行了修改):

class Meta:
    db_table = '"SCHEMA"."TABLE_NAME"'

来源:https://code.djangoproject.com/ticket/14136

我建议保留 managed = False,除非您真的知道自己在做什么。祝你好运!

您可以在执行命令之前设置所需的架构。然后在处理完查询集后返回 public 模式。

from django.db import connection
connection.set_schema(schema_name)

好吧,我解决了这个问题,让我告诉你在 django 中没有直接的方法可以做到这一点。我的应用程序的问题是,我正在使用 django 的身份验证功能以及会话处理。所有这些 table 都是由 django 在初始迁移时直接创建的。因此,models.py 文件中不存在它们,您可以简单地附加架构名称并要求您的应用程序连接到该架构的 table。

我最后做的是,我为实际上包含那些 table 的其他模式的所有 table 创建了私有同义词。如果这样做,则无需更改 Django 代码中的任何内容。您的应用程序将简单地工作,因为 oracle 将完成实际连接到正确 table 的脏活。您只需在您的应用程序中调用 table 就好像它是您自己的一样。通过这种方式,当 django 查找 tables,如 django_session、auth_user 等时,它就像往常一样简单地查询它,oracle 将它重定向到实际的 tables另一个模式。

希望这对以后遇到这个问题的人有所帮助。