【问题标题】:How to access tables from a different schema in oracle 11g using django?如何使用 django 从 oracle 11g 中的不同模式访问表?
【发布时间】:2019-06-29 19:21:24
【问题描述】:

我在 oracle 11g 中有一个名为 mi_abc 的用户。 用户在数据库中没有任何表,但可以访问另一个模式 sch_abc 中的所有表。 当我在 mi_abc 的 sch_abc 模式上运行 sqldeveloper 的普通选择查询时,它工作得非常好,但是当我使用 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

【问题讨论】:

    标签: python django django-models oracle11g cx-oracle


    【解决方案1】:

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

    我最终做的是,我为实际包含这些表的其他模式的所有表创建了私有同义词。如果你这样做,你不必改变你的 django 代码中的任何东西。您的应用程序将简单地工作,因为 oracle 将完成实际连接到正确表的繁琐工作。您只需在应用程序中调用该表,就好像它是您自己的一样。这样,当 django 查找 django_session、auth_user 等表时,它会像往常一样简单地查询它,然后 oracle 会将其重定向到另一个模式中存在的实际表。

    希望这对将来面临此问题的人有所帮助。

    【讨论】:

    • 如何为 LogEntry(DjangoAdminLog) 创建私有同义词?我不明白你的意思!
    【解决方案2】:

    这绝不是官方支持的,但这在 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,除非您真的知道自己在做什么。祝你好运!

    【讨论】:

    • @KChow,我想答案中有错字。 '\"schema\".\"table\"' 在我使用 Oracle 的项目中运行良好。
    • 我是否需要在 settings.py 文件中添加任何其他设置?
    • @borut 我的解决方案适用于 PostgreSQL,如答案中所述。 @KChow 您需要做的是打印正在生成的实际查询;我通过使用 IPython 的 embed() 函数在错误被踢出之前从 runserver 放入代码中间并打印出来来做到这一点。然后我进行了相应的调整,直到生成的 SQL 有效。我希望这会有所帮助!
    • 我认为问题出在 DJANGO_SESSION 表上。当我直接使用模式凭据时,我的 models.py 被编码。并且 migrate 自动创建了身份验证和会话处理所需的其他表。但是由于我更改了凭据以使用另一个服务 ID(用户详细信息),是否会导致应用程序找不到 django-session?
    • 因为像 DJANGO_SESSION、AUTU_USER 等类不存在于 models.py 中,而是直接从应用程序本身创建的。
    【解决方案3】:

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

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

    【讨论】:

    • 我收到错误 AttributeError: 'DatabaseWrapper' 对象没有属性 'set'。我在我的 models.py 文件中添加了你的行。我正在使用 django 1.11.18。
    猜你喜欢
    • 2011-09-20
    • 1970-01-01
    • 2016-12-05
    • 2020-02-19
    • 1970-01-01
    • 2012-05-11
    • 1970-01-01
    • 2018-08-29
    • 1970-01-01
    相关资源
    最近更新 更多