12

Q: Django が SID ではなくサービス名を使用して Oracle DB に接続する必要があることをどのように指定しますか?

やあ、

現在、SIDを使用してOracleに接続するようにDjango構成に指示しています。

ただし、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 からうまく機能します。

ありがとう - リードを本当に感謝します。

4

5 に答える 5

24

みんなありがとう、これには「文書化された」解決策があります:

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

注: HOST キーと PORT キーは辞書から除外する必要があります。そうしないと、Django は完全な "NAME" を SID として接続しようとします。

于 2013-12-10T05:24:28.480 に答える
7

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)

于 2013-11-05T16:35:46.583 に答える
3

舞台裏では、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 ソースに追加します。

于 2013-10-08T12:26:05.147 に答える