- attached sqlalchemyiniterror.py
Can't do queries in constructor of unfinished instance with autoflush and autosave
It currently seems to be impossible to run queries in the constructor of an instance which hasn't been finished yet (e.g. still has None in nullable=False attributes) when autoflush is turned on and automatic saving is enabled via scoped_session. This is because the instance will be flushed to the database with its incomplete attributes set and trigger an error.
This issue is very annoying in my application, because I want to find an association object for two objects being passed in to a constructor, but I can't. There doesn't seem to be a workaround besides moving the association object finding logic out of the constructor, which would be annoying.
I think this could be fixed by making scoped_session only auto-save instances after their constructor has completed, but there may be issues with that I'm not thinking of. If this has already been considered, I apologize for wasting your time.
Comments (10)
-
Account Deleted -
repo owner that, or not using autosave...its an ancient feature left over from version 0.1 and I really should have whacked it altogether in 0.4.
It is possible that some technicality requires the "save" operation to happen first but I will check further.
-
repo owner yeah its a fairly tedious change since two optional **kwargs to init(), _sa_session and _sa_entity_name would need to be popped before the actual init is called and then used after the init. which means id have to rearrange the code thats handling all this init business right now and/or attach things to the instance itself. also im not sure what kind of test coverage we have for all this so if its all being rearranged we'd have to write all that up as well (classes with no init, classes with init that take specific arguments, using the _sa_session and _sa_entity_name arguments, classes that throw an exception upon init, etc). all for a feature i dont think people should even be using !
-
Account Deleted Replying to zzzeek:
that, or not using autosave...its an ancient feature left over from version 0.1 and I really should have whacked it altogether in 0.4.
I see. What's the right way to disable it globally in my application without losing the query attribute that scoped_session.mapper provides? Can safely I do it like this?
It seems to work now, but is it API-breaking? If that is correct, how about making scoped_session.mapper give instances a save() method when save_on_init is disabled? I'm attaching a patch that does that.
-
Account Deleted - attached savemethodpatch.txt
Patch to make scoped_session.mapper add a save() method to instances.
-
repo owner save_on_init=False
is the official API for this right now. I'd sort of like to make itFalse
by default but that would prevent people from upgrading to 0.4.1 without code changes (but in 0.5, almost definitely....). Also, the "scoped" methodology in 0.4 removes all Session oriented methods from the instance itself, except for thequery
attribute. This is so that session methods do not produce conflicts with user-defined methods (otherwise, everytime a new method is added toSession
which people want on the "instance", we're forced to break lots of people's code). So right now you can call Session.save(instance) - Session is of course a global when you used ScopedSession. -
Account Deleted I think save() is special enough to warrant being a method on instances. Maybe delete() too, so that all CRUD operations can be done without explicitly accessing the session. That seems like a reasonable goal that puts all essential functionality on instances without over-burdening them with a huge number of methods.
-
repo owner We just removed save(), and all the others, in version 0.4. There were plenty of announcements and heads ups proposing this beforehand, going forward with it, people agreed, etc. so its a little late to change our minds again !
I'd suggest bringing it up on sqlalchemy-devel and see what they say. Note that if you really want save() in your application, just make your own mixin class and have your own classes extend it.
-
- changed status to wontfix
The query option .autoflush(False) can be used to stifle autoflush on a case-by-case basis. The attached case works with
Role.query.autoflush(False).order_by(...
added in. No traction on -devel for adding an AR-style .save construct in the core, so closing this for now. -
repo owner - removed milestone
Removing milestone: 0.4.xx (automated comment)
- Log in to comment
Demonstration of the issue.