繁体   English   中英

如何强制 Django 使用服务名称连接到 Oracle

[英]How do I force Django to connect to Oracle using Service Name

问:如何指定 Django 需要使用服务名称而不是 SID 连接到 Oracle DB?

嗨,

我目前告诉我的 Django 配置使用我的 SID 连接到 Oracle。

但是,我需要使用服务名称而不是 SID 进行连接。

APP_DATABASES={
    'default': {
            'ENGINE': 'django.db.backends.oracle',
            'NAME': 'myservice',
            'USER': 'system',
            'PASSWORD': 'admin123',
            'HOST': '192.168.1.45',
            'PORT': '1699',
    }
}

这工作正常。

但是,当我用服务名称替换“NAME”时,如下所示

 'default': {
                'ENGINE': 'django.db.backends.oracle',
                'NAME': 'myservice.bose.com',
                'USER': 'system',
                'PASSWORD': 'admin123',
                'HOST': '192.168.1.45',
                'PORT': '1699',
        }

我得到一个

ORA-12505: TNS:listener does not currently know of SID given in connect descriptor

显然 Django 告诉 Oracle 使用 SID 进行连接,这不是我希望 Django 做的。

如何指定 Django 需要使用服务而不是 SID 连接到 Oracle DB?

注意:我已经测试了上面提到的服务名称。 它在 Oracle SQL Developer 中运行良好。

谢谢 - 非常感谢潜在客户。

谢谢大家,有一个“记录在案”的解决方案:

        'default': {
                'ENGINE': 'django.db.backends.oracle',
                'NAME': 'host.db.com:1699/oracle_service.db.com',
                'USER': 'user',
                'PASSWORD': 'pass',
        }

注意:HOST 和 PORT 键需要从字典中删除 - 否则 Django 将尝试使用完整的“NAME”作为 SID 进行连接。

查看nickzam粘贴的代码:

import cx_Oracle as Database

def _connect_string(self):
    settings_dict = self.settings_dict
    if not settings_dict['HOST'].strip():
        settings_dict['HOST'] = 'localhost'
    if settings_dict['PORT'].strip():
        dsn = Database.makedsn(settings_dict['HOST'],
                               int(settings_dict['PORT']),
                               settings_dict['NAME'])
    else:
        dsn = settings_dict['NAME']
    return "%s/%s@%s" % (settings_dict['USER'],
                         settings_dict['PASSWORD'], dsn)

.. 很明显,如果您不指定“PORT”参数,则“NAME”参数将“按原样”使用。 因此,将 Oracle 连接字符串作为 'NAME' 参数传递就可以了(如果您删除了 'PORT' 参数)。

基本上这样的事情会起作用:

'default': {
    'ENGINE': 'oraclepool',
    'NAME': '(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=mydbhostname.example.com)(PORT=1521)))(CONNECT_DATA=(SERVICE_NAME=myservicename.example.com)))',
    'USER': 'scott',
    'PASSWORD': 'tiger',
}

我已经尝试使用 HOST 的 SCAN 主机名并验证这也有效。

警告:到目前为止,我的测试仅限于检查连接字符串是否被接受、建立连接以及我的应用程序是否成功提供服务,访问数据。 在依赖此配置之前,我建议进行更积极的测试 8)

在幕后,Django 使用 cx_Oracle 库连接到 Oracle 数据库。 来源: https : //github.com/django/django/blob/master/django/db/backends/oracle/base.py

import cx_Oracle as Database

def _connect_string(self):
        settings_dict = self.settings_dict
        if not settings_dict['HOST'].strip():
            settings_dict['HOST'] = 'localhost'
        if settings_dict['PORT'].strip():
            dsn = Database.makedsn(settings_dict['HOST'],
                                   int(settings_dict['PORT']),
                                   settings_dict['NAME'])
        else:
            dsn = settings_dict['NAME']
        return "%s/%s@%s" % (settings_dict['USER'],
                             settings_dict['PASSWORD'], dsn)

函数 cx_Oracle.make_dsn() 支持可选参数 service_name(摘自 cx_Oracle 文档):

cx_Oracle.makedsn(host, port, sid[, service_name])

Return a string suitable for use as the dsn for the connect() method. This string is identical to the strings that are defined by the Oracle names server or defined in the tnsnames.ora file. If you wish to use the service name instead of the sid, do not include a value for the parameter sid and use the keyword parameter service_name instead. Note This method is an extension to the DB API definition.

不幸的是,Django 没有在连接时传递service_name参数。

如果你真的需要它,向 Django 添加功能请求或修补你的本地版本的 Django 以支持 SERVICE_NAME 参数(坏主意,你需要自己支持):

def _connect_string(self):
    settings_dict = self.settings_dict
    if not settings_dict['HOST'].strip():
        settings_dict['HOST'] = 'localhost'
    if settings_dict['PORT'].strip():
        if not 'SERVICE_NAME' in settings_dict:
            dsn = Database.makedsn(settings_dict['HOST'],
                                   int(settings_dict['PORT']),
                                   settings_dict['NAME'])
        else:
            dsn = Database.makedsn(host=settings_dict['HOST'],
                                   port=int(settings_dict['PORT']),
                                   service_name=settings_dict['SERVICE_NAME'].strip())

    else:
        dsn = settings_dict['NAME']
    return "%s/%s@%s" % (settings_dict['USER'],
                         settings_dict['PASSWORD'], dsn)

然后将NAME更改为SERVICE_NAME变量到您的连接“默认”:

 'default': {
            'ENGINE': 'django.db.backends.oracle',
            'SERVICE_NAME': 'myservice.bose.com',
            'USER': 'system',
            'PASSWORD': 'admin123',
            'HOST': '192.168.1.45',
            'PORT': '1699',
    }

稍后,我会将其添加为 Django 源的拉取请求。

我使用 tnsnames.ora。 它在 Django 1.7 上对我有用。 这些是步骤:

  1. 在 tnsnames.ora 中为连接添加一个条目。

     myservice = (DESCRIPTION = (ADDRESS_LIST = (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.1.45)(PORT = 1699)) ) (CONNECT_DATA = (SERVICE_NAME = myservice.bose.com) ) )
  2. 将 Django 数据库设置更改为

    'default': { 'ENGINE': 'django.db.backends.oracle', 'NAME': 'myservice', 'USER': 'system', 'PASSWORD': 'admin123', }

详情请参考使用服务名将Django连接到Oracle数据库

这是有效的方法:

myservice =
 (DESCRIPTION = 
   (ADDRESS_LIST =
     (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.1.45)(PORT = 1699))
   )
 (CONNECT_DATA =
   (SERVICE_NAME = myservice_name)
 )
)

myservice = ''.join(trc_scan.split())

'default': {
  'ENGINE': 'django.db.backends.oracle',
  'NAME': myservice,
  'USER': 'someuser',
  'PASSWORD': 'somepsw',
}

不要在用户名和/或密码中输入以下任何字符:

@/(

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM