これは、説明するどころか、名前を付けることさえ困難な不可解な問題です。重要な事実から始めて、関連する可能性のある背景情報を示します。
2 つの mongoengine ドキュメント モデルを考えてみましょう。
class Bar(Document):
# ...
# field definitions
# ...
def bar_func(self):
pass # ...or some arbitrary code
class Foo(Document):
bar = ReferenceField(Bar)
以下は、実稼働サーバーで矛盾して生成されます。AttributeError
# Assume foo_id references a valid Foo document in Mongo
# and that its 'bar' reference is to a valid Bar document.
foo = Foo.objects.with_id(foo_id)
foo.bar.bar_func() # <-- AttributeError on 'bar_func'
エラーの場所の直前にデバッグ コードを配置するtype(foo.bar)と、文字列として評価すると<class 'bson.dbref.DBRef'>. 明らかに a には属性DBRefがありませんが、のインスタンスではなく a が返されるのはなぜですか?bar_funcDBRefBar
ReferenceField.__get__さらにデバッグ コードを実行すると、 の関数で次の条件が失敗していることがわかりますmongoengine/fields.py。
if isinstance(value, (pymongo.dbref.DBRef)):
value = _get_db().dereference(value)
しかし(pymongo.dbref.DBRef)、実際bson.dbref.DBRefには と同じように見えますtype(foo.bar)。なぜisinstance失敗するのですか?
これは物事が本当に奇妙になるところです:
id(type(foo.bar)) == id(bson.dbref.DBRef) # <-- Evaluates to False!
つまり、直接参照して得られるものtype(foo.bar)とは異なります。 実際、これら 2 つの型を調べると、関数とプロパティの異なるメモリ位置が示されます。bson.dbref.DBRefbson.dbref.DBRef__dict__
注:type(foo.bar) fooDBRefによって参照される型と区別するために、便宜上、以下では によって返される型と呼びますbson.dbref.DBRef。
さらにデバッグするためにDBRef、型の作成時にシステム モジュールを検査するメタクラスを追加するようにコードを変更しDBRef、それらのモジュールの ID のリストを の追加のクラス属性に格納しますDBRef。結果は、が作成されたときに存在するモジュールのセットが、ベアタイプが作成されたときに存在するモジュールのセットとfooDBRefは完全に異なることを示しています。bson.dbref.DBRef一方のすべてのモジュール ID は、もう一方のすべてのモジュール ID とは異なります。
関連する可能性のある要因:
- このエラーが発生するサーバーは、Apache で mod_wsgi を実行しています。
- サーバーは、wsgi の下で 2 つの異なる Django サイトを実行します (それら
site_aを および と呼びますsite_b)。 - Foo は で定義され
site_a.foo_app.models、Bar は で定義されていsite_b.bar_app.modelsます。 site_asettings.py にsite_b.bar_appはINSTALLED_APPS.- エラーを生成する要求は によって処理され
site_aます。 - が作成されたときに
site_b.*モジュールがありましたが、モジュールはありませんでした。については逆です。sys.modulesfooDBRefsite_a.*bson.dbref.DBRef - エラーが発生した後、
httpd reloadしばらくの間エラーが解消され、0 ~ 10 回の試行で元に戻ることがあります。
fooDBRefとの違いの原因を突き止めるのを手伝ってくれる人はいbson.dbref.DBRefますか?