ページの 2 回目の更新で次のエラーが発生します。DetachedInstanceError: インスタンスはセッションにバインドされていません。属性の更新操作を続行できません
DetachedInstanceError: Instance <MetadataRef at 0x107b2a0d0> is not bound to a Session; attribute refresh operation cannot proceed
- Expression: "result.meta_refs(visible_search_only=True)"
- Filename: ... ects/WebApps/PYPanel/pypanel/templates/generic/search.pt
- Location: (line 45: col 38)
- Source: ... meta_ref result.meta_refs(visible_search_only=True)" tal:omi ...
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- Arguments: repeat: {...} (0)
renderer_name: templates/home.pt
models: <list - at 0x1069e4d88>
results: <list - at 0x107c30d40>
renderer_info: <RendererHelper - at 0x1069b5650>
active_models: <list - at 0x107b69050>
query:
pagination: <NoneType - at 0x104dd5538>
req: <Request - at 0x107b4e690>
title: <NoneType - at 0x104dd5538>
generic: <NoneType - at 0x104dd5538>
request: <Request - at 0x107b4e690>
context: <RootFactory - at 0x107b12090>
page: 1
view: <Page - at 0x107b128d0>
この問題は、リクエスト間でキャッシュされたデータが共有されているようです。問題は、ローカルにのみキャッシュされることになっていることです(つまり、次のリクエストのためにすべてを再クエリします)
テンプレートの関連セクションは次のとおりです。
<div tal:repeat="meta_ref result.meta_refs(visible_search_only=True)" tal:omit-tag="True">
<div tal:define="meta result.meta(meta_ref.key, None)" tal:condition="meta is not None">
<div>${meta_ref.name} = ${meta}</div>
</div>
</div>
私の DBSession は、models.py で一度だけ宣言されます (それが違いを生む場合):
DBSession = scoped_session(sessionmaker(extension=ZopeTransactionExtension()))
キャッシュを停止すると、それが修正されます。つまり、リクエスト間でキャッシュしないようにする必要がありますが、その方法はわかりません。
これは私の meta_refs 関数です:
def meta_refs(self, visible_only=False, visible_search_only=False):
model = self.__class__.__name__
if Base._meta_refs is None:
Base._meta_refs = {}
try:
for result in DBSession.query(MetadataRef):
if result.model not in Base._meta_refs:
Base._meta_refs[result.model] = []
Base._meta_refs[result.model].append(result)
except DBAPIError:
pass
if model not in Base._meta_refs:
return []
results = []
for result in Base._meta_refs[model]:
#@TODO: Remove temporary workaround
if inspect(result).detached:
Base._meta_refs = None
return self.meta_refs(visible_only, visible_search_only)
#END of workaround
if visible_only and result.visible is False:
continue
if visible_search_only and result.visible_search is False:
continue
results.append(result)
return results
また、 meta() 関数もキャッシュし、同じ問題がないことにも注意してください。主な違いは、ORM オブジェクトではなく文字列の辞書をキャッシュすることだと思います。
開発中に pserve を使用してサービスを提供しています(それが違いを生む場合も)
sqlalchemy.inspect を使用した私のコードの一時的な回避策は機能しますが、実際にはデータが永続化されないようにしたいだけです (つまり、Base._meta_refs は、最初に 100% の時間アクセスするときに None に等しい必要があります)。
誰にもアイデアはありますか?これがリクエスト間でキャッシュされている場合、他のものも同様にキャッシュされていると確信しており、予期しない動作が発生する可能性が高すぎます.