Can't do queries in constructor of unfinished instance with autoflush and autosave

Issue #869 resolved
Former user created an issue

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)

  1. Mike Bayer 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.

  2. Mike Bayer repo owner
    • changed milestone to 0.4.xx
    • changed component to orm

    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 !

  3. Former user 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.
    
  4. Mike Bayer repo owner

    save_on_init=False is the official API for this right now. I'd sort of like to make it False 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 the query attribute. This is so that session methods do not produce conflicts with user-defined methods (otherwise, everytime a new method is added to Session 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.

  5. Former user 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.

  6. Mike Bayer 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.

  7. jek

    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.

  8. Log in to comment