5

私はDjangoに次のモデルを持っています:

class Event(models.Model):
    # some fields
    start_date = models.DateField()
    end_date = models.DateField()

Django 1.5 および cx_oracle 5.1.2 で Oracle 10g データベースを使用しています。ここでの問題は、管理インターフェイス (カレンダーから日付を選択) で新しいオブジェクトを作成しようとすると、次のエラーが発生することです。

ORA-01843: not a valid month

syncdbはとDATEのオラクルにフィールドを作成しました。これはバックエンドのバグのように見えますか、それとも何か間違っていますか?start_dateend_date

私は他のモデルを持っていDateTimeField()ますが、新しいオブジェクトを永続化すると問題なく動作します。問題はDateFieldそれ自体に関連しているように見えます。

更新:バックエンドの実装を確認しました。backends/oracle/base.py行 513 から 516 で:

cursor.execute(
    "ALTER SESSION SET NLS_DATE_FORMAT = 'YYYY-MM-DD HH24:MI:SS'"
    " NLS_TIMESTAMP_FORMAT = 'YYYY-MM-DD HH24:MI:SS.FF'"
    + (" TIME_ZONE = 'UTC'" if settings.USE_TZ else ''))

このステートメントを実行すると、insert ステートメントがDATEフィールドのリテラル値を持つことができます。バックエンドによって生成されたクエリを確認したところ、 and に挿入さ'2013-03-20'れています。日付が一致するので、理論的にはこれでうまくいくはずです!start_dateend_dateNLS_DATE_FORMAT

更新: 私のケースはcx_oracle に関連していると思います。

更新:私はまだ明確な答えを持っていないので (この問題を引き起こしているのは cx_oracle であるとほぼ確信していますが)、私を oracle に変換し、完全に正常に動作DateFieldする aに変更しました。DateTimeFieldTIMESTAMP

4

2 に答える 2

1

jtiaiの問題の説明に基づいて、次の回避策を作成しました-問題のあるsql-s(たとえば、oracle 10.5.0.2および11.2.0.1、cx_oracle 5.1.2)を呼び出す前に、NLS_DATE_FORMAT/NLS_TIMESTAMP_FORMATを再度リセットします-django/db/backends/oracleで実行しますメソッド内の /base.py def execute(...):

--- base.py 2013-10-31 12:19:24.000000000 +0100
+++ base_new.py 2013-10-31 12:20:32.000000000 +0100
@@ -707,6 +707,18 @@
         query = convert_unicode(query % tuple(args), self.charset)
         self._guess_input_sizes([params])
         try:
+            # BUG-WORKAROUND: ulr1-131031 
+            # https://stackoverflow.com/a/17269719/565525
+            # It's actually a bug in the Oracle 10.5.0.2 and 11.2.0.1. Bug can be reproduced as following:
+            #     - set NLS_TIMESTAMP_FORMAT in session.
+            #     - Run any implicit or explicit TO_DATE conversion with unicode data.
+            #     - **Next implicit or explicit TO_TIMESTAMP with unicode data will trigger internal reset of timestamp format.**
+            #     - All consecutive TO_TIMESTAMP will fail and TO_CHAR of timestamp will produce invalid output.
+            self.cursor.execute(
+                "ALTER SESSION SET NLS_DATE_FORMAT = 'YYYY-MM-DD HH24:MI:SS'"
+                " NLS_TIMESTAMP_FORMAT = 'YYYY-MM-DD HH24:MI:SS.FF'"
+                + (" TIME_ZONE = 'UTC'" if settings.USE_TZ else ''))
+
             return self.cursor.execute(query, self._param_generator(params))
         except Database.IntegrityError as e:
             six.reraise(utils.IntegrityError, utils.IntegrityError(*tuple(e.args)), sys.exc_info()[2])
于 2013-10-31T11:51:25.243 に答える