the ORM can't persist any value for "delivery_method" unless there is an actual 
attribute set event.

If you are saying session.add(DeliveryAddress()) and flushing, these are the 
options for "deliveryaddress.delivery_method":

1. the value has no setting and is not present in the INSERT statement - it 
gets set as NULL in the DB.

2. the value has no setting, but you have a python or server side default set 
up on it.  At before_insert() time, that value is still None so that can't be 
what you're doing.

3. The DeliveryAddress() constructor sets delivery_method, so there's an 
attribute set event.

So I can only guess that you're looking for the None here?   I guess there's 
some odd relationship to this Settings object such that it already exists in 
the DB with some other value such that you actually need to positively set 
None.      In any case, to have something happen upon DeliveryAddress(), you 
can either place that logic as part of __init__() (regular Python!) or if that 
bothers you, you can also set up the init() event for the DeliveryAddress class.

If all of these options don't suit you and you absolutely insist on the 
before_insert event, it is very easy to add to your declarative base a mixin 
that sets these up for you (see 
http://docs.sqlalchemy.org/en/rel_0_9/orm/extensions/declarative.html#declare-last):

class BeforeInsertMixin(object):
    @classmethod
    def __declare_last__(cls):
        if hasattr(cls, 'before_insert'):
            event.listen(cls, 'before_insert', cls.before_insert)

Base = declarative_base(cls=BeforeInsertMixin)

class DeliveryAddress(Base):
    # ...

    @classmethod
    def before_insert(cls, mapper, connection, target):
        #...


if you want to change the signature, no problem:

class BeforeInsertMixin(object):
    @classmethod
    def __declare_last__(cls):
        if hasattr(cls, 'before_insert'):
            @event.listens_for(cls, 'before_insert')
            def before_insert(mapper, connection, target):
                target.before_insert(object_session(target))


class DeliveryAddress(Base):
    # ...

    def before_insert(self, session):
        #...
            
These are "frameworky" types of hooks that SQLAlchemy would prefer to remain 
agnostic of, but it provides for you all the components you need to create 
whatever system of hooks you'd like.





On Jun 2, 2014, at 8:04 AM, Alex Grönholm <[email protected]> wrote:

> That's the first thing I tried, but validators don't get called unless you 
> explicitly set a value to the column.
> 
> So for something like session.add(DeliveryAddress()), the validator doesn't 
> get called.
> 
> maanantai, 2. kesäkuuta 2014 14.27.47 UTC+3 Michael Bayer kirjoitti:
> 
> On Jun 2, 2014, at 1:47 AM, Alex Grönholm <[email protected]> wrote: 
> 
> > This has been a problem for me for years. 
> > 
> > class DeliveryAddress(Base, Address): 
> >     ... 
> >     delivery_method = Column(String) 
> >     ... 
> > 
> > @event.listens_for(DeliveryAddress, 'before_insert') 
> > def before_insert_deliveryaddress(mapper, connection, target): 
> >     settings = object_session(target).query(Settings).one() 
> >     target.delivery_method = settings.default_delivery_method 
> > 
> > Is there absolutely no way to encapsulate this logic cleanly in the actual 
> > class? 
> 
> 
> I use an attribute event for that, and more often just a simple @validates.   
> 
> @validates("default_delivery_method") 
> def _set_delivery_method(self, key, value): 
>     self.settings.delivery_method = value 
>     return value 
> 
> 
> 
> 
> -- 
> You received this message because you are subscribed to the Google Groups 
> "sqlalchemy" group.
> To unsubscribe from this group and stop receiving emails from it, send an 
> email [email protected].
> To post to this group, send email to [email protected].
> Visit this group at http://groups.google.com/group/sqlalchemy.
> For more options, visit https://groups.google.com/d/optout.

-- 
You received this message because you are subscribed to the Google Groups 
"sqlalchemy" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/sqlalchemy.
For more options, visit https://groups.google.com/d/optout.

Reply via email to