the correlate_except tells it exactly what to "correlate" and what not to, preventing that "auto-correlation" error.
try it out and then show me how you'd like the SQL to be adjusted given a particular Query. On Tue, Oct 31, 2017 at 1:32 PM, Tucker Beck <tucker.b...@gmail.com> wrote: > I'll try this out. The comparator was put in so that queries comparing the > hybrid_type_name against a string would do a proper sub-select against the > EntityType table. If we didn't provide the comparator, the hybrid expression > was used and the resulting query was orders of magnitude slower. Does adding > the correlate_except() method in there compel sqlalchemy to do a sub-select? > > On Tue, Oct 31, 2017 at 10:19 AM, Mike Bayer <mike...@zzzcomputing.com> > wrote: >> >> that error can be fixed using correlate_except: >> >> @classmethod >> def hybrid_type_name_subquery(cls): >> return select([HybridType.name]).\ >> where(HybridType.id == cls.hybrid_type_id).\ >> correlate_except(HybridType).as_scalar() >> >> but now that we're looking at your queries in full, the comparator >> makes no sense. It just pulls in HybridType into the FROM clause and >> makes a broken query with "FROM hybrids, hybrid_types" without them >> being joined. >> >> your tests pass just using plain @expression and keeping the >> subqueries contained: >> >> @hybrid_property >> def hybrid_type_name(self): >> return self.hybrid_type.name >> >> @hybrid_type_name.setter >> def hybrid_type_name(self, value): >> self.hybrid_type_id = ( >> select([HybridType.id]). >> where(HybridType.name == value) >> ) >> >> @hybrid_type_name.expression >> def hybrid_type_name(cls): >> return cls.hybrid_type_name_subquery() >> >> @classmethod >> def hybrid_type_name_subquery(cls): >> return select([HybridType.name]).\ >> where(HybridType.id == cls.hybrid_type_id).as_scalar() >> >> >> for extra protection with correlation, correlate_except looks like this: >> >> @classmethod >> def hybrid_type_name_subquery(cls): >> return select([HybridType.name]).\ >> where(HybridType.id == cls.hybrid_type_id).\ >> correlate_except(HybridType).as_scalar() >> >> >> >> >> >> >> On Tue, Oct 31, 2017 at 12:18 PM, Tucker Beck <tucker.b...@gmail.com> >> wrote: >> > Thanks so much for getting back so fast, Mike! >> > >> > For some background: we started with the expression, but then discovered >> > that the performance we were getting was pretty bad on queries when the >> > table was large and we were filtering by the hybrid attribute. Postgres >> > was >> > doing a sequence-scan, and the plan was pretty bad. So, I learned about >> > custom comparators, and that helped the performance for those kind of >> > queries really dramatically. I didn't realize that the comparator was >> > not >> > meant to be used along-side an expression; I thought they served >> > different >> > purposes. >> > >> > Trying your suggestion worked great for order_by. However, filtering on >> > the >> > hybrid attribute is failing with complaints about correlation. >> > >> > I revised the code as: >> > >> > from sqlalchemy import * >> > from sqlalchemy.orm import * >> > from sqlalchemy.ext.declarative import declarative_base, declared_attr >> > from sqlalchemy.ext.hybrid import hybrid_property, Comparator >> > >> > Base = declarative_base() >> > >> > class classproperty(property): >> > """A decorator that behaves like @property except that operates >> > on classes rather than instances. >> > >> > The decorator is currently special when using the declarative >> > module, but note that the >> > :class:`~.sqlalchemy.ext.declarative.declared_attr` >> > decorator should be used for this purpose with declarative. >> > >> > """ >> > >> > def __init__(self, fget, *arg, **kw): >> > super(classproperty, self).__init__(fget, *arg, **kw) >> > self.__doc__ = fget.__doc__ >> > >> > def __get__(desc, self, cls): >> > return desc.fget(cls) >> > >> > >> > class ModelBase(Base): >> > __abstract__ = True >> > >> > def __repr__(self): >> > return "{} ({}:{})".format(type(self).__name__, self.name, >> > self.id) >> > >> > >> > class HybridType(ModelBase): >> > __tablename__ = 'hybrid_types' >> > id = Column(Integer, primary_key=True) >> > name = Column(Text) >> > >> > >> > class HybridModel(ModelBase): >> > __tablename__ = 'hybrids' >> > >> > id = Column(Integer, primary_key=True) >> > name = Column(Text) >> > hybrid_type_id = Column(Integer, ForeignKey('hybrid_types.id'), >> > nullable=False) >> > hybrid_type = relationship('HybridType') >> > >> > def __init__(self, *args, **kwargs): >> > self.hybrid_type_name = self.hybrid_type_identity >> > return super().__init__(*args, **kwargs) >> > >> > @classproperty >> > def hybrid_type_identity(cls): >> > return cls.__name__ >> > >> > @declared_attr >> > def __mapper_args__(cls): >> > return dict( >> > polymorphic_on=cls.hybrid_type_name_subquery(), >> > polymorphic_identity=cls.hybrid_type_identity, >> > ) >> > >> > @hybrid_property >> > def hybrid_type_name(self): >> > return self.hybrid_type.name >> > >> > @hybrid_type_name.setter >> > def hybrid_type_name(self, value): >> > self.hybrid_type_id = ( >> > select([HybridType.id]). >> > where(HybridType.name == value) >> > ) >> > >> > @classmethod >> > def hybrid_type_name_subquery(cls): >> > return select([HybridType.name]).where(HybridType.id == >> > cls.hybrid_type_id).as_scalar() >> > >> > class HybridComparator(Comparator): >> > >> > def __clause_element__(self): >> > return self.expression.hybrid_type_name_subquery() >> > >> > def operate(self, op, other): >> > return op(HybridType.id, >> > select([HybridType.id]).where(HybridType.name == other).as_scalar()) >> > >> > @hybrid_type_name.comparator >> > def hybrid_type_name(cls): >> > return cls.HybridComparator(cls) >> > >> > >> > class HybridAlpha(HybridModel): >> > pass >> > >> > >> > class HybridBeta(HybridModel): >> > pass >> > >> > >> > e = create_engine("sqlite://", echo=False) >> > Base.metadata.create_all(e) >> > session = Session(e) >> > >> > >> > session.add(HybridType(name=HybridAlpha.hybrid_type_identity)) >> > session.add(HybridType(name=HybridBeta.hybrid_type_identity)) >> > session.add(HybridAlpha(name='alpha_instance')) >> > session.add(HybridBeta(name='beta_instance')) >> > >> > >> > print("--- Test query from base hybrid model ---") >> > assert session.query(HybridModel).count() == 2 >> > print("passed") >> > print("--- Test query from base derived hybrid model ---") >> > assert session.query(HybridAlpha).count() == 1 >> > assert session.query(HybridBeta).count() == 1 >> > print("passed") >> > print("--- Test query order_by on hybrid attribute ---") >> > assert [ >> > x.hybrid_type_name for x >> > in session.query(HybridModel).order_by(HybridModel.hybrid_type_name) >> > ] == [HybridAlpha.hybrid_type_identity, HybridBeta.hybrid_type_identity] >> > print("passed") >> > print("--- Test query filter_by on hybrid attribute ---") >> > assert >> > >> > session.query(HybridModel).filter_by(hybrid_type_name=HybridAlpha.hybrid_type_identity).count() >> > == 1 >> > print("passed") >> > print("--- Test query filtered on hybrid attribute ---") >> > assert session.query(HybridModel).filter(HybridAlpha.hybrid_type_name == >> > HybridAlpha.hybrid_type_identity).count() == 1 >> > print("passed") >> > >> > >> > And here's the output >> > >> > /venv:cem/ $ python demo.py >> > --- Test query from base hybrid model --- >> > passed >> > --- Test query from base derived hybrid model --- >> > passed >> > --- Test query order_by on hybrid attribute --- >> > passed >> > --- Test query filter_by on hybrid attribute --- >> > Traceback (most recent call last): >> > File "demo.py", line 124, in <module> >> > assert >> > >> > session.query(HybridModel).filter_by(hybrid_type_name=HybridAlpha.hybrid_type_identity).correlate(HybridModel).count() >> > == 1 >> > File >> > >> > "/home/tbeck/.virtualenvs/cem/lib/python3.5/site-packages/sqlalchemy/orm/query.py", >> > line 3089, in count >> > return self.from_self(col).scalar() >> > File >> > >> > "/home/tbeck/.virtualenvs/cem/lib/python3.5/site-packages/sqlalchemy/orm/query.py", >> > line 2843, in scalar >> > ret = self.one() >> > File >> > >> > "/home/tbeck/.virtualenvs/cem/lib/python3.5/site-packages/sqlalchemy/orm/query.py", >> > line 2814, in one >> > ret = self.one_or_none() >> > File >> > >> > "/home/tbeck/.virtualenvs/cem/lib/python3.5/site-packages/sqlalchemy/orm/query.py", >> > line 2784, in one_or_none >> > ret = list(self) >> > File >> > >> > "/home/tbeck/.virtualenvs/cem/lib/python3.5/site-packages/sqlalchemy/orm/query.py", >> > line 2855, in __iter__ >> > return self._execute_and_instances(context) >> > File >> > >> > "/home/tbeck/.virtualenvs/cem/lib/python3.5/site-packages/sqlalchemy/orm/query.py", >> > line 2878, in _execute_and_instances >> > result = conn.execute(querycontext.statement, self._params) >> > File >> > >> > "/home/tbeck/.virtualenvs/cem/lib/python3.5/site-packages/sqlalchemy/engine/base.py", >> > line 945, in execute >> > return meth(self, multiparams, params) >> > File >> > >> > "/home/tbeck/.virtualenvs/cem/lib/python3.5/site-packages/sqlalchemy/sql/elements.py", >> > line 263, in _execute_on_connection >> > return connection._execute_clauseelement(self, multiparams, params) >> > File >> > >> > "/home/tbeck/.virtualenvs/cem/lib/python3.5/site-packages/sqlalchemy/engine/base.py", >> > line 1046, in _execute_clauseelement >> > if not self.schema_for_object.is_default else None) >> > File "<string>", line 1, in <lambda> >> > File >> > >> > "/home/tbeck/.virtualenvs/cem/lib/python3.5/site-packages/sqlalchemy/sql/elements.py", >> > line 436, in compile >> > return self._compiler(dialect, bind=bind, **kw) >> > File >> > >> > "/home/tbeck/.virtualenvs/cem/lib/python3.5/site-packages/sqlalchemy/sql/elements.py", >> > line 442, in _compiler >> > return dialect.statement_compiler(dialect, self, **kw) >> > File >> > >> > "/home/tbeck/.virtualenvs/cem/lib/python3.5/site-packages/sqlalchemy/sql/compiler.py", >> > line 435, in __init__ >> > Compiled.__init__(self, dialect, statement, **kwargs) >> > File >> > >> > "/home/tbeck/.virtualenvs/cem/lib/python3.5/site-packages/sqlalchemy/sql/compiler.py", >> > line 216, in __init__ >> > self.string = self.process(self.statement, **compile_kwargs) >> > File >> > >> > "/home/tbeck/.virtualenvs/cem/lib/python3.5/site-packages/sqlalchemy/sql/compiler.py", >> > line 242, in process >> > return obj._compiler_dispatch(self, **kwargs) >> > File >> > >> > "/home/tbeck/.virtualenvs/cem/lib/python3.5/site-packages/sqlalchemy/sql/visitors.py", >> > line 81, in _compiler_dispatch >> > return meth(self, **kw) >> > File >> > >> > "/home/tbeck/.virtualenvs/cem/lib/python3.5/site-packages/sqlalchemy/sql/compiler.py", >> > line 1738, in visit_select >> > text, select, inner_columns, froms, byfrom, kwargs) >> > File >> > >> > "/home/tbeck/.virtualenvs/cem/lib/python3.5/site-packages/sqlalchemy/sql/compiler.py", >> > line 1817, in _compose_select_body >> > for f in froms]) >> > File >> > >> > "/home/tbeck/.virtualenvs/cem/lib/python3.5/site-packages/sqlalchemy/sql/compiler.py", >> > line 1817, in <listcomp> >> > for f in froms]) >> > File >> > >> > "/home/tbeck/.virtualenvs/cem/lib/python3.5/site-packages/sqlalchemy/sql/visitors.py", >> > line 81, in _compiler_dispatch >> > return meth(self, **kw) >> > File >> > >> > "/home/tbeck/.virtualenvs/cem/lib/python3.5/site-packages/sqlalchemy/sql/compiler.py", >> > line 1379, in visit_alias >> > asfrom=True, **kwargs) + \ >> > File >> > >> > "/home/tbeck/.virtualenvs/cem/lib/python3.5/site-packages/sqlalchemy/sql/annotation.py", >> > line 80, in _compiler_dispatch >> > self, visitor, **kw) >> > File >> > >> > "/home/tbeck/.virtualenvs/cem/lib/python3.5/site-packages/sqlalchemy/sql/visitors.py", >> > line 81, in _compiler_dispatch >> > return meth(self, **kw) >> > File >> > >> > "/home/tbeck/.virtualenvs/cem/lib/python3.5/site-packages/sqlalchemy/sql/compiler.py", >> > line 1716, in visit_select >> > for name, column in select._columns_plus_names >> > File >> > >> > "/home/tbeck/.virtualenvs/cem/lib/python3.5/site-packages/sqlalchemy/sql/compiler.py", >> > line 1716, in <listcomp> >> > for name, column in select._columns_plus_names >> > File >> > >> > "/home/tbeck/.virtualenvs/cem/lib/python3.5/site-packages/sqlalchemy/sql/compiler.py", >> > line 1488, in _label_select_column >> > **column_clause_args >> > File >> > >> > "/home/tbeck/.virtualenvs/cem/lib/python3.5/site-packages/sqlalchemy/sql/visitors.py", >> > line 81, in _compiler_dispatch >> > return meth(self, **kw) >> > File >> > >> > "/home/tbeck/.virtualenvs/cem/lib/python3.5/site-packages/sqlalchemy/sql/compiler.py", >> > line 664, in visit_label >> > OPERATORS[operators.as_] + \ >> > File >> > >> > "/home/tbeck/.virtualenvs/cem/lib/python3.5/site-packages/sqlalchemy/sql/visitors.py", >> > line 81, in _compiler_dispatch >> > return meth(self, **kw) >> > File >> > >> > "/home/tbeck/.virtualenvs/cem/lib/python3.5/site-packages/sqlalchemy/sql/compiler.py", >> > line 576, in visit_grouping >> > return "(" + grouping.element._compiler_dispatch(self, **kwargs) + >> > ")" >> > File >> > >> > "/home/tbeck/.virtualenvs/cem/lib/python3.5/site-packages/sqlalchemy/sql/visitors.py", >> > line 81, in _compiler_dispatch >> > return meth(self, **kw) >> > File >> > >> > "/home/tbeck/.virtualenvs/cem/lib/python3.5/site-packages/sqlalchemy/sql/compiler.py", >> > line 1685, in visit_select >> > froms = self._setup_select_stack(select, entry, asfrom, lateral) >> > File >> > >> > "/home/tbeck/.virtualenvs/cem/lib/python3.5/site-packages/sqlalchemy/sql/compiler.py", >> > line 1788, in _setup_select_stack >> > implicit_correlate_froms=asfrom_froms) >> > File >> > >> > "/home/tbeck/.virtualenvs/cem/lib/python3.5/site-packages/sqlalchemy/sql/selectable.py", >> > line 2843, in _get_display_froms >> > "manually." % self) >> > sqlalchemy.exc.InvalidRequestError: Select statement 'SELECT >> > hybrid_types.name >> > FROM hybrid_types, hybrids >> > WHERE hybrid_types.id = hybrids.hybrid_type_id' returned no FROM clauses >> > due >> > to auto-correlation; specify correlate(<tables>) to control correlation >> > manually. >> > >> > I've tried looking for some examples for how to use correlate and tried >> > stuffing it in a few places and still haven't gotten around this error. >> > What >> > am I missing? >> > >> > (Thanks again so much for the quick response) >> > >> > >> > On Mon, Oct 30, 2017 at 4:58 PM, Mike Bayer <mike...@zzzcomputing.com> >> > wrote: >> >> >> >> On Mon, Oct 30, 2017 at 6:43 PM, Tucker Beck <tucker.b...@gmail.com> >> >> wrote: >> >> > I wrestled through getting a model heirarchy to work with >> >> > single-table >> >> > inheritance that is polymorphic on a hybrid attribute on this mailing >> >> > list a >> >> > while ago. >> >> > >> >> > see: >> >> > https://groups.google.com/d/topic/sqlalchemy/KJXSHwbhbLA/discussion >> >> > >> >> > The problem I'm running into now is that it doesn't seem to work >> >> > correctly >> >> > when I want to use the hybrid property for filtering or ordering. >> >> > This seems to be an issue with auto-correlation, but I can't seem to >> >> > figure >> >> > out how to get it working. >> >> > >> >> > Here is a runnable example: >> >> >> >> OK so lets pdb: >> >> >> >> class HybridBeta(HybridModel): >> >> pass >> >> >> >> >> >> session = Session() >> >> >> >> import pdb >> >> pdb.set_trace() >> >> >> >> >> >> >> >> what are we getting from HybridModel.hybrid_type_name: >> >> >> >> (Pdb) HybridModel.hybrid_type_name >> >> <sqlalchemy.orm.attributes.create_proxied_attribute.<locals>.Proxy >> >> object at 0x7f95594ca200> >> >> >> >> >> >> that's not right. I see there's a @comparator and also an >> >> @expression. Those actually aren't designed to be used together, >> >> you'd use one or the other. I'm not sure what you're trying to do >> >> but based on the organization of what I see you'd want to do this: >> >> >> >> @classmethod >> >> def hybrid_type_name_subquery(cls): >> >> return select([HybridType.name]).where(HybridType.id == >> >> cls.hybrid_type_id).as_scalar() >> >> >> >> class HybridComparator(Comparator): >> >> >> >> def __clause_element__(self): >> >> return self.expression.hybrid_type_name_subquery() >> >> >> >> def operate(self, op, other): >> >> return op(HybridType.id, >> >> select([HybridType.id]).where(HybridType.name == other).as_scalar()) >> >> >> >> @hybrid_type_name.comparator >> >> def hybrid_type_name(cls): >> >> return cls.HybridComparator(cls) >> >> >> >> >> >> which gives you a query: >> >> >> >> >> >> print(session.query(HybridModel).order_by(HybridModel.hybrid_type_name)) >> >> >> >> SELECT hybrids.id AS hybrids_id, hybrids.name AS hybrids_name, >> >> hybrids.hybrid_type_id AS hybrids_hybrid_type_id, (SELECT >> >> hybrid_types.name >> >> FROM hybrid_types >> >> WHERE hybrid_types.id = hybrids.hybrid_type_id) AS _sa_polymorphic_on >> >> FROM hybrids ORDER BY (SELECT hybrid_types.name >> >> FROM hybrid_types >> >> WHERE hybrid_types.id = hybrids.hybrid_type_id) >> >> >> >> >> >> >> >> >> >> >> >> > >> >> > from sqlalchemy import * >> >> > from sqlalchemy.orm import * >> >> > from sqlalchemy.ext.declarative import declarative_base, >> >> > declared_attr >> >> > from sqlalchemy.ext.hybrid import hybrid_property, Comparator >> >> > >> >> > Base = declarative_base() >> >> > >> >> > class classproperty(property): >> >> > """A decorator that behaves like @property except that operates >> >> > on classes rather than instances. >> >> > >> >> > The decorator is currently special when using the declarative >> >> > module, but note that the >> >> > :class:`~.sqlalchemy.ext.declarative.declared_attr` >> >> > decorator should be used for this purpose with declarative. >> >> > >> >> > """ >> >> > >> >> > def __init__(self, fget, *arg, **kw): >> >> > super(classproperty, self).__init__(fget, *arg, **kw) >> >> > self.__doc__ = fget.__doc__ >> >> > >> >> > def __get__(desc, self, cls): >> >> > return desc.fget(cls) >> >> > >> >> > >> >> > class ModelBase(Base): >> >> > __abstract__ = True >> >> > >> >> > def __repr__(self): >> >> > return "{} ({}:{})".format(type(self).__name__, self.name, >> >> > self.id) >> >> > >> >> > >> >> > class HybridType(ModelBase): >> >> > __tablename__ = 'hybrid_types' >> >> > id = Column(Integer, primary_key=True) >> >> > name = Column(Text) >> >> > >> >> > >> >> > class HybridModel(ModelBase): >> >> > __tablename__ = 'hybrids' >> >> > >> >> > id = Column(Integer, primary_key=True) >> >> > name = Column(Text) >> >> > hybrid_type_id = Column(Integer, ForeignKey('hybrid_types.id'), >> >> > nullable=False) >> >> > hybrid_type = relationship('HybridType') >> >> > >> >> > def __init__(self, *args, **kwargs): >> >> > self.hybrid_type_name = self.hybrid_type_identity >> >> > return super().__init__(*args, **kwargs) >> >> > >> >> > @classproperty >> >> > def hybrid_type_identity(cls): >> >> > return cls.__name__ >> >> > >> >> > @declared_attr >> >> > def __mapper_args__(cls): >> >> > return dict( >> >> > polymorphic_on=cls.hybrid_type_name_subquery(), >> >> > polymorphic_identity=cls.hybrid_type_identity, >> >> > ) >> >> > >> >> > @hybrid_property >> >> > def hybrid_type_name(self): >> >> > return self.hybrid_type.name >> >> > >> >> > @hybrid_type_name.setter >> >> > def hybrid_type_name(self, value): >> >> > self.hybrid_type_id = ( >> >> > select([HybridType.id]). >> >> > where(HybridType.name == value) >> >> > ) >> >> > >> >> > @hybrid_type_name.expression >> >> > def hybrid_type_name(cls): >> >> > return cls.hybrid_type_name_subquery() >> >> > >> >> > @classmethod >> >> > def hybrid_type_name_subquery(cls): >> >> > return select([HybridType.name]).where(HybridType.id == >> >> > cls.hybrid_type_id).as_scalar() >> >> > >> >> > class HybridComparator(Comparator): >> >> > >> >> > def operate(self, op, other): >> >> > return op(HybridType.id, >> >> > select([HybridType.id]).where(HybridType.name == other).as_scalar()) >> >> > >> >> > @hybrid_type_name.comparator >> >> > def hybrid_type_name(cls): >> >> > return cls.HybridComparator(cls) >> >> > >> >> > >> >> > class HybridAlpha(HybridModel): >> >> > pass >> >> > >> >> > >> >> > class HybridBeta(HybridModel): >> >> > pass >> >> > >> >> > >> >> > e = create_engine("sqlite://", echo=False) >> >> > Base.metadata.create_all(e) >> >> > session = Session(e) >> >> > >> >> > >> >> > session.add(HybridType(name=HybridAlpha.hybrid_type_identity)) >> >> > session.add(HybridType(name=HybridBeta.hybrid_type_identity)) >> >> > session.add(HybridAlpha(name='alpha_instance')) >> >> > session.add(HybridBeta(name='beta_instance')) >> >> > >> >> > >> >> > print("--- Test query from base hybrid model ---") >> >> > assert session.query(HybridModel).count() == 2 >> >> > print("passed") >> >> > print("--- Test query from base derived hybrid model ---") >> >> > assert session.query(HybridAlpha).count() == 1 >> >> > assert session.query(HybridBeta).count() == 1 >> >> > print("passed") >> >> > print("--- Test query order_by on hybrid attribute ---") >> >> > assert [ >> >> > x.hybrid_type_name for x >> >> > in >> >> > session.query(HybridModel).order_by(HybridModel.hybrid_type_name) >> >> > ] == [HybridAlpha.hybrid_type_identity, >> >> > HybridBeta.hybrid_type_identity] >> >> > print("passed") >> >> > print("--- Test query filter_by on hybrid attribute ---") >> >> > assert >> >> > >> >> > >> >> > session.query(HybridModel).filter_by(hybrid_type_name=HybridAlpha.hybrid_type_identity).count() >> >> > == 1 >> >> > print("passed") >> >> > print("--- Test query filtered on hybrid attribute ---") >> >> > assert session.query(HybridModel).filter(HybridAlpha.hybrid_type_name >> >> > == >> >> > HybridAlpha.hybrid_type_identity).count() == 1 >> >> > print("passed") >> >> > >> >> > >> >> > >> >> > Running this results in the following out put: >> >> > $ python demo.py >> >> > --- Test query from base hybrid model --- >> >> > passed >> >> > --- Test query from base derived hybrid model --- >> >> > passed >> >> > --- Test query order_by on hybrid attribute --- >> >> > Traceback (most recent call last): >> >> > File "demo.py", line 121, in <module> >> >> > in >> >> > session.query(HybridModel).order_by(HybridModel.hybrid_type_name) >> >> > File "<string>", line 2, in order_by >> >> > File >> >> > >> >> > >> >> > "/Users/tbeck/.virtualenvs/cem/lib/python3.5/site-packages/sqlalchemy/orm/base.py", >> >> > line 201, in generate >> >> > fn(self, *args[1:], **kw) >> >> > File >> >> > >> >> > >> >> > "/Users/tbeck/.virtualenvs/cem/lib/python3.5/site-packages/sqlalchemy/orm/query.py", >> >> > line 1589, in order_by >> >> > criterion = self._adapt_col_list(criterion) >> >> > File >> >> > >> >> > >> >> > "/Users/tbeck/.virtualenvs/cem/lib/python3.5/site-packages/sqlalchemy/orm/query.py", >> >> > line 256, in _adapt_col_list >> >> > for o in cols >> >> > File >> >> > >> >> > >> >> > "/Users/tbeck/.virtualenvs/cem/lib/python3.5/site-packages/sqlalchemy/orm/query.py", >> >> > line 256, in <listcomp> >> >> > for o in cols >> >> > File >> >> > >> >> > >> >> > "/Users/tbeck/.virtualenvs/cem/lib/python3.5/site-packages/sqlalchemy/sql/elements.py", >> >> > line 4191, in _literal_as_label_reference >> >> > return _literal_as_text(element) >> >> > File >> >> > >> >> > >> >> > "/Users/tbeck/.virtualenvs/cem/lib/python3.5/site-packages/sqlalchemy/sql/elements.py", >> >> > line 4230, in _literal_as_text >> >> > "instead" % type(element) >> >> > sqlalchemy.exc.ArgumentError: SQL expression object or string >> >> > expected, >> >> > got >> >> > object of type <class >> >> > 'sqlalchemy.ext.declarative.api.DeclarativeMeta'> >> >> > instead >> >> > >> >> > -- >> >> > SQLAlchemy - >> >> > The Python SQL Toolkit and Object Relational Mapper >> >> > >> >> > http://www.sqlalchemy.org/ >> >> > >> >> > To post example code, please provide an MCVE: Minimal, Complete, and >> >> > Verifiable Example. See http://stackoverflow.com/help/mcve for a full >> >> > description. >> >> > --- >> >> > You received this message because you are subscribed to the Google >> >> > Groups >> >> > "sqlalchemy" group. >> >> > To unsubscribe from this group and stop receiving emails from it, >> >> > send >> >> > an >> >> > email to sqlalchemy+unsubscr...@googlegroups.com. >> >> > To post to this group, send email to sqlalchemy@googlegroups.com. >> >> > Visit this group at https://groups.google.com/group/sqlalchemy. >> >> > For more options, visit https://groups.google.com/d/optout. >> >> >> >> -- >> >> SQLAlchemy - >> >> The Python SQL Toolkit and Object Relational Mapper >> >> >> >> http://www.sqlalchemy.org/ >> >> >> >> To post example code, please provide an MCVE: Minimal, Complete, and >> >> Verifiable Example. See http://stackoverflow.com/help/mcve for a full >> >> description. >> >> --- >> >> You received this message because you are subscribed to a topic in the >> >> Google Groups "sqlalchemy" group. >> >> To unsubscribe from this topic, visit >> >> https://groups.google.com/d/topic/sqlalchemy/M4b5y_d69u0/unsubscribe. >> >> To unsubscribe from this group and all its topics, send an email to >> >> sqlalchemy+unsubscr...@googlegroups.com. >> >> To post to this group, send email to sqlalchemy@googlegroups.com. >> >> Visit this group at https://groups.google.com/group/sqlalchemy. >> >> For more options, visit https://groups.google.com/d/optout. >> > >> > >> > >> > >> > -- >> > -=Tucker A. Beck=- >> > >> > Illustrious Writer >> > Devious Coder >> > Last Hope for the Free World >> > Also, Modest >> > >> > -- >> > SQLAlchemy - >> > The Python SQL Toolkit and Object Relational Mapper >> > >> > http://www.sqlalchemy.org/ >> > >> > To post example code, please provide an MCVE: Minimal, Complete, and >> > Verifiable Example. See http://stackoverflow.com/help/mcve for a full >> > description. >> > --- >> > You received this message because you are subscribed to the Google >> > Groups >> > "sqlalchemy" group. >> > To unsubscribe from this group and stop receiving emails from it, send >> > an >> > email to sqlalchemy+unsubscr...@googlegroups.com. >> > To post to this group, send email to sqlalchemy@googlegroups.com. >> > Visit this group at https://groups.google.com/group/sqlalchemy. >> > For more options, visit https://groups.google.com/d/optout. >> >> -- >> SQLAlchemy - >> The Python SQL Toolkit and Object Relational Mapper >> >> http://www.sqlalchemy.org/ >> >> To post example code, please provide an MCVE: Minimal, Complete, and >> Verifiable Example. See http://stackoverflow.com/help/mcve for a full >> description. >> --- >> You received this message because you are subscribed to a topic in the >> Google Groups "sqlalchemy" group. >> To unsubscribe from this topic, visit >> https://groups.google.com/d/topic/sqlalchemy/M4b5y_d69u0/unsubscribe. >> To unsubscribe from this group and all its topics, send an email to >> sqlalchemy+unsubscr...@googlegroups.com. >> To post to this group, send email to sqlalchemy@googlegroups.com. >> Visit this group at https://groups.google.com/group/sqlalchemy. >> For more options, visit https://groups.google.com/d/optout. > > > > > -- > -=Tucker A. Beck=- > > Illustrious Writer > Devious Coder > Last Hope for the Free World > Also, Modest > > -- > SQLAlchemy - > The Python SQL Toolkit and Object Relational Mapper > > http://www.sqlalchemy.org/ > > To post example code, please provide an MCVE: Minimal, Complete, and > Verifiable Example. See http://stackoverflow.com/help/mcve for a full > description. > --- > You received this message because you are subscribed to the Google Groups > "sqlalchemy" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to sqlalchemy+unsubscr...@googlegroups.com. > To post to this group, send email to sqlalchemy@googlegroups.com. > Visit this group at https://groups.google.com/group/sqlalchemy. > For more options, visit https://groups.google.com/d/optout. -- SQLAlchemy - The Python SQL Toolkit and Object Relational Mapper http://www.sqlalchemy.org/ To post example code, please provide an MCVE: Minimal, Complete, and Verifiable Example. See http://stackoverflow.com/help/mcve for a full description. --- You received this message because you are subscribed to the Google Groups "sqlalchemy" group. To unsubscribe from this group and stop receiving emails from it, send an email to sqlalchemy+unsubscr...@googlegroups.com. To post to this group, send email to sqlalchemy@googlegroups.com. Visit this group at https://groups.google.com/group/sqlalchemy. For more options, visit https://groups.google.com/d/optout.