這是一個令人費解的問題,這是很難甚至名字,更不用說形容。我將從基本事實開始,然後給出可能相關的背景信息。怪誕與mongoengine ReferenceField
考慮兩個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'>
。顯然,一個DBRef
沒有一個bar_func
屬性,但爲什麼一個DBRef
返回的Bar
實例的呢?
進一步調試代碼表明以下條件在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)
是不同bson.dbref.DBRef
不是通過直接引用bson.dbref.DBRef
獲得的一個。實際上,檢查這兩種類型的__dict__
會爲其功能和屬性顯示不同的存儲位置。
注:我會打電話的type(foo.bar)
fooDBRef
下面方便的返回類型,它由bson.dbref.DBRef
引用的類型區分。
爲了進一步調試,我修改了DBRef
代碼以添加在創建DBRef
類型的時間檢查該系統模塊元類,並且存儲這些模塊中的DBRef
一個額外的類屬性的ID的列表。結果顯示,創建fooDBRef
時存在的模塊集合爲,與創建裸露的bson.dbref.DBRef
類型時存在的模塊集合完全不同。其中一個的所有模塊ID與另一個的所有模塊ID不同。
一些可能相關的因素:
- 上Apache下出現此錯誤運行mod_wsgi的服務器。
- 服務器在wsgi下運行兩個不同的Django站點(稱它們爲
site_a
和site_b
)。 - foo是
site_a.foo_app.models
定義和酒吧在site_b.bar_app.models
定義。 site_a
設置。py在INSTALLED_APPS
中有site_b.bar_app
。- 產生錯誤的請求由
site_a
處理。 - 模塊
sys.modules
fooDBRef
創建時,但沒有site_a.*
模塊。bson.dbref.DBRef
的情況正好相反。 - 的
httpd reload
錯誤後有時會消失一小會兒,和0-10次嘗試內的某個時候返回。
誰能幫我找出是什麼原因造成fooDBRef
從bson.dbref.DBRef
不同?
我們使用嵌入模式。我切換到守護進程模式,加入WSGIDaemonProcess,WSGIProcessGroup和WSGIApplicationGroup指示到虛擬主機的條目,並且WSGISocketPrefix指令到配置的根級別。它似乎有效!至少,這個錯誤還沒有發生,而且通常情況下它會有這個問題。我將等待一天左右,確保它消失,然後接受答案。謝謝您的幫助! – Alanyst
我很滿意它現在的作品。再次感謝。 – Alanyst