qwertyさん
この現象は https://code.djangoproject.com/ticket/10933 で報告されている問題が原因のように思えます。
この問題は、Django か mod_wsgi のどこかで decimal がリロードされたために、value に渡された Decimal
オブジェクトのクラスオブジェクトが消えてしまい、リロード後に作られた Decimal クラスと一致しなくなることによって引き起こされます。
--------------------
# coding: utf-8
"""
# doctest用にDjangoを初期化する
>>> from django.conf import settings
>>> settings.configure()
# DecimalField を作成
>>> from django.db.models import fields
>>> df1 = fields.DecimalField()
# decimal オブジェクトを作って変換してみると、うまくいく
>>> d = fields.decimal.Decimal()
>>> df1.to_python(d)
Decimal('0')
# fields.__init__ の参照している decimal と、sys.modules からの参照を消して、 decimal モジュールをアンロードする
>>> del fields.decimal; import sys; del sys.modules['decimal']
# decimal をインポートしなおし、 fields.decimal にバインドしなおすと。。。。
>>> import decimal
>>> fields.decimal = decimal
# to_python が問題を起こし始めます。
>>> df1.to_python(d)
Traceback (most recent call last):
...
TypeError: Cannot convert Decimal('0') to Decimal
# インポートしなおした decimal.Decimal で作った Decimal オブジェクトは、問題を起こしません。
>>> d2 = decimal.Decimal()
>>> df1.to_python(d2)
Decimal('0')
# オブジェクトの**タイプ名**がDecimalの時には一旦文字列に変換するようなデコレータを書く
>>> def wrapper(func):
... def wrapped(self, value):
... if type(value).__name__=='Decimal':
... return func(self, str(value))
... else:
... return func(self, value)
... return wrapped
...
# このデコレータで to_python をラップすると。。。
>>> fields.DecimalField.to_python = wrapper(fields.DecimalField.to_python)
# to_python は再びまともな挙動に戻ります。
>>> df1.to_python(d)
Decimal('0')
"""
if __name__=='__main__':
from doctest import testmod
testmod()
----------------------
上のチケットには、回避するにはパッチを当てよと書かれていますが、汚い方法でよければ、上のようなデコレータを使って、
django.db.models.fields.DecimalField.to_python をスナッチすれば解決できると思います。
2011年9月18日2:41 qwerty <[email protected]>:
> django のadmin サイトでデータを保存するとたまに上記エラーが発生します。
> 既存のデータを何も変更せず保存しても確率的には3回に1回くらいです。 特定のmodelsでのみ発生します
> decimal 以外のエラーは発生しません・
> このmodels.py でsaveは上書きしてません。
> ローカルでのrunserver では発生しませんし、defaultの値が間違いなら常にエラーになると思うのですが。
>
> 見当がつきませんのでお知恵を拝借できればと思います。よろしくお願いいたします。
>
> 動作環境
> python 2.6
> django 1.3
>
> CACHE_BACKEND = 'memcached
> 'ENGINE': 'sqlite3'
>
> 'mod_wsgi.application_group': 'www.@@@|/******',
> 'mod_wsgi.callable_object': 'application',
> 'mod_wsgi.handler_script': '',
> 'mod_wsgi.input_chunked': '0',
> 'mod_wsgi.listener_host': '',
> 'mod_wsgi.listener_port': '80',
> 'mod_wsgi.process_group': '',
> 'mod_wsgi.request_handler': 'wsgi-script',
> 'mod_wsgi.script_reloading': '1',
> 'mod_wsgi.version': (3, 3),
> 'wsgi.errors': <mod_wsgi.Log object at 0x2b04199caa70>,
> 'wsgi.file_wrapper': <built-in method file_wrapper of mod_wsgi.Adapter
> object at 0x2b0419c42b70>,
> 'wsgi.input': <mod_wsgi.Input object at 0x2b0419b16670>,
> 'wsgi.multiprocess': True,
> 'wsgi.multithread': False,
> 'wsgi.run_once': False,
> 'wsgi.url_scheme': 'http',
> 'wsgi.version': (1, 1)}>
>
> --
> ----------------- http://djangoproject.jp/ -----------------
> You received this message because you are subscribed to the Google Groups
> "django-ja" group.
> To post to this group, send email to [email protected]
> To unsubscribe from this group, send email to
> [email protected]
> For more options, visit this group at
> http://groups.google.com/group/django-ja
--
Yasushi Mausda
http://ymasuda.jp/
whosaysni at twitter/gmail
--
----------------- http://djangoproject.jp/
-----------------
You received this message because you are subscribed to the Google Groups
"django-ja" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at http://groups.google.com/group/django-ja