def test_without_default_polymorphic_buildit_newstyle( self, two_pjoin_fixture, use_star ): """how would we do these concrete polymorphic queries using 2.0 style, and not any old and esoteric features like "polymorphic_union" ? """ ( session, Employee, Engineer, Manager, Hacker, pjoin, pjoin2, jdoe, sally, jenn, hacker, ) = two_pjoin_fixture # make a union using the entities as given and wpoly from it. # a UNION is a UNION. there is no way around having to write # out filler columns. concrete inh is really not a good choice # when you need to select heterogeneously stmt = union_all( select( literal("engineer").label("type"), Engineer, null().label("nickname"), ), select(literal("hacker").label("type"), Hacker), ).subquery() # issue: if we make this with_polymorphic(Engineer, [Hacker], ...), # it blows up and tries to add the "engineer" table for unknown reasons if use_star: wp = with_polymorphic( Engineer, "*", stmt, polymorphic_on=stmt.c.type ) else: wp = with_polymorphic( Engineer, [Engineer, Hacker], stmt, polymorphic_on=stmt.c.type ) result = session.execute(select(wp)).scalars() eq_( sorted(repr(obj) for obj in result), [ "Engineer Jenn knows how to program", "Hacker Karina 'Badass' knows how to hack", ], )
def test_without_default_polymorphic_six(self, two_pjoin_fixture): ( session, Employee, Engineer, Manager, Hacker, pjoin, pjoin2, jdoe, sally, jenn, hacker, ) = two_pjoin_fixture # this test is adapting what used to use from_self(). # it's a weird test but how we would do this would be we would only # apply with_polymorprhic once, after we've created whatever # subquery we want. subq = pjoin2.select().subquery() wp2 = with_polymorphic(Engineer, "*", subq, polymorphic_on=subq.c.type) eq_( sorted([repr(x) for x in session.query(wp2)]), [ "Engineer Jenn knows how to program", "Hacker Karina 'Badass' knows how to hack", ], )
def test_without_default_polymorphic_two(self, two_pjoin_fixture): ( session, Employee, Engineer, Manager, Hacker, pjoin, pjoin2, jdoe, sally, jenn, hacker, ) = two_pjoin_fixture wp = with_polymorphic( Employee, "*", pjoin, polymorphic_on=pjoin.c.type ) eq_( sorted([repr(x) for x in session.query(wp)]), [ "Employee Jdoe", "Engineer Jenn knows how to program", "Hacker Karina 'Badass' knows how to hack", "Manager Sally knows how to manage things", ], )
def _get_document(self, clazz, id, clazz_locale=None, lang=None): """Get a document with either a single locale (if `lang is given) or with all locales. If no document exists for the given id, a `HTTPNotFound` exception is raised. """ if not lang: document_query = DBSession. \ query(clazz). \ filter(getattr(clazz, 'document_id') == id). \ options(joinedload('geometry')) document_query = add_load_for_locales(document_query, clazz, clazz_locale) document_query = add_load_for_profiles(document_query, clazz) document = document_query.first() else: locales_type = with_polymorphic(DocumentLocale, clazz_locale) \ if clazz_locale else DocumentLocale locales_attr = getattr(clazz, 'locales') locales_type_eager = locales_attr.of_type(clazz_locale) \ if clazz_locale else locales_attr document_query = DBSession. \ query(clazz). \ join(locales_type). \ filter(getattr(clazz, 'document_id') == id). \ filter(DocumentLocale.lang == lang). \ options(joinedload('geometry')).\ options(contains_eager(locales_type_eager, alias=locales_type)) document_query = add_load_for_profiles(document_query, clazz) document = document_query.first() if not document: # the requested locale might not be available, try to get the # document without locales document_query = DBSession. \ query(clazz). \ filter(getattr(clazz, 'document_id') == id). \ options(joinedload('geometry')) document_query = add_load_for_profiles(document_query, clazz) document = document_query.first() if document: # explicitly set `locales` to an empty list so that they # are no lazy loaded document.locales = [] # also detach the document from the session, so that the # empty list is not persisted DBSession.expunge(document) if not document: raise HTTPNotFound('document not found') return document
def _get_document(self, clazz, id, clazz_locale=None, lang=None): """Get a document with either a single locale (if `lang is given) or with all locales. If no document exists for the given id, a `HTTPNotFound` exception is raised. """ if not lang: document_query = DBSession. \ query(clazz). \ filter(getattr(clazz, 'document_id') == id). \ options(joinedload('geometry')) document_query = add_load_for_locales( document_query, clazz, clazz_locale) document_query = add_load_for_profiles(document_query, clazz) document = document_query.first() else: locales_type = with_polymorphic(DocumentLocale, clazz_locale) \ if clazz_locale else DocumentLocale locales_attr = getattr(clazz, 'locales') locales_type_eager = locales_attr.of_type(clazz_locale) \ if clazz_locale else locales_attr document_query = DBSession. \ query(clazz). \ join(locales_type). \ filter(getattr(clazz, 'document_id') == id). \ filter(DocumentLocale.lang == lang). \ options(joinedload('geometry')).\ options(contains_eager(locales_type_eager, alias=locales_type)) document_query = add_load_for_profiles(document_query, clazz) document = document_query.first() if not document: # the requested locale might not be available, try to get the # document without locales document_query = DBSession. \ query(clazz). \ filter(getattr(clazz, 'document_id') == id). \ options(joinedload('geometry')) document_query = add_load_for_profiles(document_query, clazz) document = document_query.first() if document: # explicitly set `locales` to an empty list so that they # are no lazy loaded document.locales = [] # also detach the document from the session, so that the # empty list is not persisted DBSession.expunge(document) if not document: raise HTTPNotFound('document not found') return document
def _get_current_document(self, document_id, lang, clazz, clazz_locale): locales_type = with_polymorphic(DocumentLocale, clazz_locale) \ if clazz_locale else DocumentLocale locales_attr = getattr(clazz, 'locales') locales_type_eager = locales_attr.of_type(clazz_locale) \ if clazz_locale else locales_attr document_query = DBSession. \ query(clazz). \ join(locales_type). \ filter(getattr(clazz, 'document_id') == document_id). \ filter(DocumentLocale.lang == lang). \ options(joinedload('geometry')). \ options(contains_eager(locales_type_eager, alias=locales_type)) return document_query.first()
def _load_document_info(self, document_id, lang, clazz): is_route = clazz == Route locales_type = with_polymorphic(DocumentLocale, RouteLocale) \ if is_route else DocumentLocale locales_attr = getattr(clazz, 'locales') locales_type_eager = locales_attr.of_type(RouteLocale) \ if is_route else locales_attr locales_load_only = [ DocumentLocale.lang, DocumentLocale.title, DocumentLocale.version ] if is_route: locales_load_only.append(RouteLocale.title_prefix) document_query = DBSession. \ query(clazz). \ options(load_only( Document.document_id, Document.version, Document.redirects_to, Document.protected)). \ join(locales_type). \ filter(getattr(clazz, 'document_id') == document_id). \ filter(DocumentLocale.lang == lang). \ options(contains_eager(locales_type_eager, alias=locales_type). load_only(*locales_load_only)) document_query = add_load_for_profiles(document_query, clazz) document = document_query.first() if not document: # the requested locale might not be available, try to get the # document with all locales and set the "best" document_query = DBSession. \ query(clazz). \ options(load_only( Document.document_id, Document.version, Document.redirects_to, Document.protected)). \ filter(getattr(clazz, 'document_id') == document_id). \ options(joinedload(locales_type_eager). load_only(*locales_load_only)) document_query = add_load_for_profiles(document_query, clazz) document = document_query.first() if not document: raise HTTPNotFound('document not found') set_best_locale([document], lang) if document.redirects_to: return { 'redirects_to': document.redirects_to, 'available_langs': get_available_langs(document.redirects_to) } assert len(document.locales) == 1 locale = document.locales[0] return { 'document_id': document.document_id, 'locales': [{ 'lang': locale.lang, 'title': locale.title if clazz != UserProfile else document.name, 'title_prefix': locale.title_prefix if is_route else None }] }
def _load_document_info(self, document_id, lang, clazz): is_route = clazz == Route locales_type = with_polymorphic(DocumentLocale, RouteLocale) \ if is_route else DocumentLocale locales_attr = getattr(clazz, 'locales') locales_type_eager = locales_attr.of_type(RouteLocale) \ if is_route else locales_attr locales_load_only = [ DocumentLocale.lang, DocumentLocale.title, DocumentLocale.version] if is_route: locales_load_only.append(RouteLocale.title_prefix) document_query = DBSession. \ query(clazz). \ options(load_only( Document.document_id, Document.version, Document.redirects_to, Document.protected)). \ join(locales_type). \ filter(getattr(clazz, 'document_id') == document_id). \ filter(DocumentLocale.lang == lang). \ options(contains_eager(locales_type_eager, alias=locales_type). load_only(*locales_load_only)) document_query = add_load_for_profiles(document_query, clazz) document = document_query.first() if not document: # the requested locale might not be available, try to get the # document with all locales and set the "best" document_query = DBSession. \ query(clazz). \ options(load_only( Document.document_id, Document.version, Document.redirects_to, Document.protected)). \ filter(getattr(clazz, 'document_id') == document_id). \ options(joinedload(locales_type_eager). load_only(*locales_load_only)) document_query = add_load_for_profiles(document_query, clazz) document = document_query.first() if not document: raise HTTPNotFound('document not found') set_best_locale([document], lang) if document.redirects_to: return { 'redirects_to': document.redirects_to, 'available_langs': get_available_langs( document.redirects_to) } assert len(document.locales) == 1 locale = document.locales[0] return { 'document_id': document.document_id, 'locales': [{ 'lang': locale.lang, 'title': locale.title if clazz != UserProfile else document.name, 'title_prefix': locale.title_prefix if is_route else None }] }