Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bulk_replace assumes incoming values are ORM objects #3896

Closed
sqlalchemy-bot opened this issue Jan 25, 2017 · 5 comments
Closed

bulk_replace assumes incoming values are ORM objects #3896

sqlalchemy-bot opened this issue Jan 25, 2017 · 5 comments
Labels
bug Something isn't working orm
Milestone

Comments

@sqlalchemy-bot
Copy link
Collaborator

Migrated issue, originally created by Michael Bayer (@zzzeek)

There is no way to coerce incoming values to a collection without awkward use of two different APIs for full coverage:

from sqlalchemy import *
from sqlalchemy.orm import *
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm.collections import collection

Base = declarative_base()


# awkward
class MyCollection(list):

    # awkward
    @collection.converter
    def convert(self, value):
        return [B(data=v['data']) for v in value]

    # awkward - can't even use collection.appender! 
    # so inconsistent!  "converter" does not fit with the other
    # methods at all, should be an event, and/or bulk_replace
    # needs a huge rethink
#    @collection.appender
#    def append(self, value):
#        # convert here - doesn't work

class A(Base):
    __tablename__ = 'a'
    id = Column(Integer, primary_key=True)

                           # awkward
    bs = relationship("B", collection_class=MyCollection)

    @validates('bs')
    def _go(self, key, value):
        # because of @converter, awkward
        if not isinstance(value, B):
            value = B(data=value['data'])
        return value


class B(Base):
    __tablename__ = 'b'
    id = Column(Integer, primary_key=True)
    a_id = Column(ForeignKey('a.id'))
    data = Column(String)


a1 = A()

# requires @converter
a1.bs = [{"data": "one"}, {"data": "two"}, {"data": "three"}]

# requres AttributeEvent / @validates
a1.bs.append({"data": "four"})

tentative 1.2 to consider a better system but this might be longer term

@sqlalchemy-bot
Copy link
Collaborator Author

Changes by Michael Bayer (@zzzeek):

  • edited description

@sqlalchemy-bot
Copy link
Collaborator Author

Michael Bayer (@zzzeek) wrote:

https://gerrit.sqlalchemy.org/298 should be an easy commit, will allow @validates to work for bulk sets. an application that's using collection.converter right now might trip on this, but will note this in the migration notes for 1.2.

@sqlalchemy-bot
Copy link
Collaborator Author

Michael Bayer (@zzzeek) wrote:

Add bulk_replace event, integrate with @validates

Added new attribute event :meth:.AttributeEvents.bulk_replace.
This event is triggered when a collection is assigned to a
relationship, before the incoming collection is compared with the
existing one. This early event allows for conversion of incoming
non-ORM objects as well. The event is integrated with the
@validates decorator.

The @validates decorator now allows the decorated method to receive
objects from a "bulk collection set" operation that have not yet
been compared to the existing collection. This allows incoming values
to be converted to compatible ORM objects as is already allowed
from an "append" event. Note that this means that the
@validates method is called for all values during a collection
assignment, rather than just the ones that are new.

Change-Id: I27f59db008d9e521d31a3e30143d7cd997e4b7b3
Fixes: #3896

9974e9a

@sqlalchemy-bot
Copy link
Collaborator Author

Changes by Michael Bayer (@zzzeek):

  • changed status to closed

@sqlalchemy-bot
Copy link
Collaborator Author

Michael Bayer (@zzzeek) wrote:

serious regression: #4171

@sqlalchemy-bot sqlalchemy-bot added bug Something isn't working orm labels Nov 27, 2018
@sqlalchemy-bot sqlalchemy-bot added this to the 1.2 milestone Nov 27, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working orm
Projects
None yet
Development

No branches or pull requests

1 participant