我在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
已在oracle中为DATE
和start_date
创建了end_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
个字段的文字值。我检查了后端生成的查询,并在'2013-03-20'
和start_date
中插入了end_date
。日期与NLS_DATE_FORMAT
匹配,因此理论上这应该有效!
更新:我认为我的案例是related to cx_oracle。
更新:由于我仍然没有明确的答案(虽然我几乎可以肯定它是导致此问题的cx_oracle),但我将DateField
更改为{{1}这转化为oracle的DateTimeField
,并且完美无缺。
答案 0 :(得分:1)
基于jtiai问题description,我做了以下解决方法 - 在调用任何有问题的sql-s(例如oracle 10.5.0.2和11.2.0.1,cx_oracle 5.1.2)之前,重置NLS_DATE_FORMAT / NLS_TIMESTAMP_FORMAT再次 - 在方法def execute(...)
中的django / db / backends / oracle / base.py中完成:
--- 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])
答案 1 :(得分:-2)
错误原因是您输入了日期,但日期的月份部分不是有效月份。 Oracle为此问题提供了解决方案。
1 - 使用MONTH
或MON
格式掩码重新输入日期值。月份的有效值为:
January
February
March
.......
//and soon
OR
Jan
Feb
Mar
.......
//and soon
2 - 如果上述解决方案失败,请改用to_date function
。
to_date( string1, [ format_mask ], [ nls_language ] )