On 26 май, 18:24, "Michael Bayer" <mike...@zzzcomputing.com> wrote: > Denis S. Otkidach wrote: > > > such ability in SQLAlchemy. There is a suggestion ( > >http://groups.google.com/group/sqlalchemy/browse_thread/thread/bcd10e... > > ) to provide custom query_cls. This probably worked a year ago, but > > doesn't work now. > > that should absolutely work now. "doesn't work" is never a very useful > explanation of a problem.
Sure, my report is not verbose enough. Here is a part of traceback when my QueryPublic is used: [... here is code equivalent to: for link in doc.links: link.ref_doc.events_sections[0].slug # <- failes here ...] File "/home/web/third-party/SQLAlchemy-0.5.4p1-py2.5.egg/sqlalchemy/ orm/attributes.py", line 158, in __get__ return self.impl.get(instance_state(instance), instance_dict (instance)) File "/home/web/third-party/SQLAlchemy-0.5.4p1-py2.5.egg/sqlalchemy/ orm/attributes.py", line 374, in get value = callable_() File "/home/web/third-party/SQLAlchemy-0.5.4p1-py2.5.egg/sqlalchemy/ orm/strategies.py", line 559, in __call__ return q.get(ident) File "/home/web/third-party/SQLAlchemy-0.5.4p1-py2.5.egg/sqlalchemy/ orm/query.py", line 442, in get return self._get(key, ident) File "/home/web/third-party/SQLAlchemy-0.5.4p1-py2.5.egg/sqlalchemy/ orm/query.py", line 1396, in _get q.__no_criterion_condition("get") File "/home/web/third-party/SQLAlchemy-0.5.4p1-py2.5.egg/sqlalchemy/ orm/query.py", line 271, in __no_criterion_condition raise sa_exc.InvalidRequestError("Query.%s() being called on a Query with existing criterion. " % meth) InvalidRequestError: Query.get() being called on a Query with existing criterion. And when I redefine get() it comes a bit farther: [... here is code equivalent to: for link in doc.links: link.ref_doc.events_sections[0].slug link.ref_doc.short_title # <- failes here ...] File "/home/web/third-party/SQLAlchemy-0.5.4p1-py2.5.egg/sqlalchemy/ orm/attributes.py", line 158, in __get__ return self.impl.get(instance_state(instance), instance_dict (instance)) File "/home/web/third-party/SQLAlchemy-0.5.4p1-py2.5.egg/sqlalchemy/ orm/attributes.py", line 374, in get value = callable_() File "/home/web/third-party/SQLAlchemy-0.5.4p1-py2.5.egg/sqlalchemy/ orm/state.py", line 171, in __call__ attr.impl.key in unmodified File "/home/web/third-party/SQLAlchemy-0.5.4p1-py2.5.egg/sqlalchemy/ orm/mapper.py", line 1834, in _load_scalar_attributes result = session.query(mapper).from_statement(statement)._get (None, only_load_props=attribute_names, refresh_state=state) File "<string>", line 1, in <lambda> File "/home/web/third-party/SQLAlchemy-0.5.4p1-py2.5.egg/sqlalchemy/ orm/query.py", line 51, in generate assertion(self, fn.func_name) File "/home/web/third-party/SQLAlchemy-0.5.4p1-py2.5.egg/sqlalchemy/ orm/query.py", line 281, in __no_clauseelement_condition self.__no_criterion_condition(meth) File "/home/web/third-party/SQLAlchemy-0.5.4p1-py2.5.egg/sqlalchemy/ orm/query.py", line 271, in __no_criterion_condition raise sa_exc.InvalidRequestError("Query.%s() being called on a Query with existing criterion. " % meth) InvalidRequestError: Query.from_statement() being called on a Query with existing criterion. Condition is: class Doc([...base declarative model...]): [...] state = Column(Integer, nullable=False, default=0, index=True) [...] PUBLISHED = 4 public_condition = (state==PUBLISHED) Here doc (retrieved from session by id) and doc_ref (via 2 relations) are instances of Doc class. Other models here don't have public_condition yet. > > Here is query class I pass as query_cls argument to sessionmaker: > > > def QueryPublic(entities, session=None): > > query = Query(entities, session) > > # XXX I haven't ever seen examples with several entities, so I can > > test > > # this case. > > assert len(entities)==1, entities > > # XXX Sometimes it's not a model class or mapper, so the following > > fails. > > cls = _class_to_mapper(entities[0]).class_ > > public_condition = getattr(cls, 'public_condition', None) > > if public_condition is not None: > > query = query.filter(public_condition) > > return query > > > This works for simple queries, but any access to relation gives an > > about Query.get() used for query with condition (this wasn't a case > > for 0.4.x). > > get() should never be called when there's any filtering applied. its a > nonsensical operation so 0.5 likes to tell you about it. I don't call it explicitly, but it is called internally when I access property defined with relation(). > > OK, i've redefined get() method to be less restrictive in > > cost of performance: > > > class HackedQuery(Query): > > > def get(self, ident): > > # XXX This works for case when primary key is constructed of > > id field > > # only. > > if isinstance(ident, (tuple, list)): > > assert len(ident)==1 > > ident = ident[0] > > return self.filter_by(id=ident).first() > > > This helped for some properties access, but not all. Right now I have > > a similar error for statement_from() method. Probably I can fix this > > too, but how many methods I have to overwrite to make it working > > ever? > > its not clear here if you want filtering to be applied when lazyloaders > fire off or not. Also, get() is really a special method- you've > completely broken it above, such that it won't first check the session for > the desired object (a major performance element), it wont check the > expired status, etc. Performance is certainly less important than avoiding a lot of errors due to forgotten manually applied filters, so it's OK for us. And I don't understand the problem with expired status, in fact it'd prefer to forbid reloading of objects at all in public part of project. > I'm a little mystified what such a criterion could be that would work > across all your tables. I don't understand what's wrong with using > relation() to define the appropriate primaryjoin is. If you don't want to > "type" it over and over again, just make your own relation() function that > applies the desired primaryjoin in an automated fashion and then returns > the result of SQLAlchemy's relation(). Do you mean I have to create separate model definitions for public and private parts of site? It doesn't seem sane to me. I've used such filtering across all tables for over 10 years with other DB tools, and it saved me a lot of work. Why not using it with SA? --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "sqlalchemy" group. To post to this group, send email to sqlalchemy@googlegroups.com To unsubscribe from this group, send email to sqlalchemy+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/sqlalchemy?hl=en -~----------~----~----~----~------~----~------~--~---