- edited description
bulk_replace assumes incoming values are ORM objects
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
Comments (3)
-
reporter -
reporter 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.
-
reporter - changed status to resolved
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→ <<cset 9974e9a46bdf>>
- Log in to comment