Using an _AssociationList subclass as proxy_factory is awkward
The standard association proxies used by the association proxy only blank out the foreign key column when you remove an item from the list. For many use cases this is not ideal since it leaves a lot of orphans in the database, something which the schema might not even allow.
As a workaround I wanted to customize the default _AssocationList to remove the target object instead of just removing it from the underlying collection. It turns out this is impossible: AssociationProxy instantiaties the built-in proxies with different parameters than a a proxy_factory you pass in by hand. This makes it impossible to make a derived class from _AssociationList and use that as proxy factory.
Comments (8)
-
Account Deleted -
Account Deleted For completeness sake: this is the rest of that class. Perhaps someone else finds this helpful as well.
def _delete(self, index): obj=self.col[index](index) state=orm.attributes.instance_state(obj) # Be careful: if an object has not been persisted we have to expunge, # not delete. if state.key is None: meta.Session.expunge(obj) else: meta.Session.delete(obj) del self.col[index](index) def __delitem__(self, index): self._delete(index) def remove(self, value): for i, val in enumerate(self): if val == value: self._delete(i) return raise ValueError("value not in list")
-
Account Deleted .. of course this specific use case is invalid since one can just use the ''delete-orphan'' cascade option on the relation. The basic problem of it being impossible to use a customised version of the standard proxy factories remains though.
-
- assigned issue to
- changed title to Using an _AssociationList subclass as proxy_factory is awkward
Extending one of the _private types is hardly impossible. The getter and setter simply need to be manufactured to suit. Either use an adapting factory:
def mylist_factory(lazy_collection, creator, value_attr): return MyList(lazy_collection, creator, operator.attrgetter(value_attr), lambda o, v: setattr(o, attr, value_attr))
or adapt in the
__init__
of your subclass:def __init__(self, lazy_collection, creator, value_attr): super(MyList, self).__init__(lazy_collection, creator, operator.attrgetter(value_attr), lambda o, v: setattr(o, attr, value_attr))
Will consider some sort of short-circuit if
proxy_factory
is a subclass of one of the built in proxies. -
repo owner Replying to guest:
The standard association proxies used by the association proxy only blank out the foreign key column when you remove an item from the list. For many use cases this is not ideal since it leaves a lot of orphans in the database, something which the schema might not even allow.
Since jek already replied I guess I'm missing something, but aren't you just looking for
delete, delete-orphan
cascade here ? the "blank out the foreign keys" behavior is only one of two behaviors you can choose from. -
repo owner - changed milestone to 0.5.xx
-
repo owner the
self
argument is required to the proxy_factory for subclassing in 0.6 so this has been added in dc1fc3a8972ce79d3c63289018335fcb92dd45d8 plus a unit test illustrating a subclass as proxy_factory example. -
repo owner - removed milestone
Removing milestone: 0.6.0 (automated comment)
- Log in to comment
For reference, this is the workaround I ended up using: