Otrzymuję następujący błąd podczas drugiego odświeżania strony: DetachedInstanceError: Instancja nie jest związana z sesją; przypisują odświeżyć operacja nie może przystąpićPython (framework Pyramid) utrzymuje dane między żądaniami i nie mogę zrozumieć, dlaczego
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>
Problem wydaje się być jakiś podział pamięci podręcznej danych pomiędzy żądaniami. Chodzi o to, że to ma tylko być buforowane lokalnie (czyli wszystko ponowne zapytanie do następnego życzenie)
Odpowiednia sekcja szablonu jest:
<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>
Moja DBSession jest zadeklarowany tylko raz, w modelach .py (jeśli to ma znaczenie):
DBSession = scoped_session(sessionmaker(extension=ZopeTransactionExtension()))
Gdybym zatrzymać buforowanie to rozwiązuje go, co oznacza, że wystarczy, aby go nie buforują pomiędzy żądaniami, które nie wiem jak to zrobić.
To mój meta_refs funkcja:
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
Warto również zauważyć, że meta() funkcja buforuje również i nie ma ten sam problem - myślę, że prawdopodobnie Kluczową różnicą jest to, że buforuje dyktować ciągi zamiast obiektów ORM.
Używam pserve jej służyć, a ja jestem jej rozwój (także jeśli to robi różnicę)
Tymczasowe obejście w moim kodu, używając sqlalchemy.inspect, działa, ale ja naprawdę chcę dane po prostu nie trwają (tzn. Base._meta_refs powinny być równe None za pierwszym razem, gdy uzyskuję do nich dostęp w 100% przypadków).
Ktoś ma jakieś pomysły? Jeśli jest to buforowane między żądaniami, jestem pewien, że jest jeszcze coś innego, a to jest zbyt duży potencjał dla nieoczekiwanego zachowania.
Chociaż jestem za uproszczeniem, muszę wszystkie dane przez 1 zapytaniu SQL (i nie chce im się utrzymywać między wniosków). Aby pobrać wszystkie wiersze lub średnio 3,8 ms, potrzeba 4,3 ms średniej, co jest mało wydajne, jeśli pobieram więcej niż jeden model, który jest niezbędny dla większości żądań. Rzędy są małe, co ma wpływ na to. W każdym razie, w jaki sposób chciałbym przechowywać dane w obiekcie żądania? Brzmi to wykonalnie, ale nie mogę znaleźć dokumentacji na temat robienia czegoś takiego. –
Nie wiedziałem, że potrzebujesz MetadataRef dla więcej niż jednego modelu podczas serwowania pojedynczego żądania, ale moim celem było to, że twój kod jest zbyt skomplikowany dla tego, co wydaje się robić. Kwerenda SQLAlchemy jest świetnym narzędziem i nie ma żadnego powodu, aby nie używać go na rzecz pętli i "ręcznego" filtrowania. –
W każdym razie odpowiedź na twoje pytanie jest w pierwszym zdaniu mojego pierwotnego postu.Prosimy o zignorowanie reszty. –