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

メールによる返信