librelist archives

« back to archive

Flask-SQLAlchemy Signal Support

Flask-SQLAlchemy Signal Support

From:
Armin Ronacher
Date:
2010-08-03 @ 12:32
Hi,

Flask-SQLAlchemy just got signal support.  Additionally it's now 
possible to omit the table name in which case the class name is used.

Here a real-worldish example:

from flask import Flask
from flaskext.sqlalchemy import SQLAlchemy, models_comitted

app = Flask(__name__)
db = SQLAlchemy(app)

class Post(db.Model):
     id = db.Column('post_id', db.Integer, primary_key=True)
     title = db.Column(db.String(200))
     text = db.Column(db.String)

     def __init__(self, title, text):
         self.title = title
         self.text = text

def update_post_search_entry(post, operation):
     if operation == 'insert':
         searchindex.insert(post)
     elif operation == 'update':
         searchindex.update(post)
     elif operation == 'delete':
         searchindex.delete(post)

def on_models_committed(sender, changes):
     for model, change in changes:
         if isinstance(model, Post):
             update_post_search_entry(model, change)

models_committed.connect(on_models_committed, sender=app)



The update_post_search_entry here obviously would update the entry in a 
searchindex for some search backend.  Think Whoosh or Xapian.

There is another signal that is executed right before things are 
committed but due to how sessions in SQLAlchemy work you still could not 
change a value on there, so I doubt the usefulness.  Do you think 
another signal might be useful?


Regards,
Armin

Re: [flask] Flask-SQLAlchemy Signal Support

From:
Dan Jacob
Date:
2010-08-03 @ 16:08
Thanks for adding this.

I'd suggest a couple of changes.

Having to loop through all the committed models and check which
operation seems a bit cumbersome. Would the following be possible:

from flaskext.sqlalchemy import after_delete

class Post(db.Model):
     ......

def remove_from_search(sender, instance):
    search_api.remove(instance)

after_delete.connect(remove_from_search, Post)

This would do pretty much the same as models_committed, but would
filter the model/operation accordingly.

On 3 August 2010 13:32, Armin Ronacher <armin.ronacher@active-4.com> wrote:
> Hi,
>
> Flask-SQLAlchemy just got signal support.  Additionally it's now
> possible to omit the table name in which case the class name is used.
>
> Here a real-worldish example:
>
> from flask import Flask
> from flaskext.sqlalchemy import SQLAlchemy, models_comitted
>
> app = Flask(__name__)
> db = SQLAlchemy(app)
>
> class Post(db.Model):
>     id = db.Column('post_id', db.Integer, primary_key=True)
>     title = db.Column(db.String(200))
>     text = db.Column(db.String)
>
>     def __init__(self, title, text):
>         self.title = title
>         self.text = text
>
> def update_post_search_entry(post, operation):
>     if operation == 'insert':
>         searchindex.insert(post)
>     elif operation == 'update':
>         searchindex.update(post)
>     elif operation == 'delete':
>         searchindex.delete(post)
>
> def on_models_committed(sender, changes):
>     for model, change in changes:
>         if isinstance(model, Post):
>             update_post_search_entry(model, change)
>
> models_committed.connect(on_models_committed, sender=app)
>
>
>
> The update_post_search_entry here obviously would update the entry in a
> searchindex for some search backend.  Think Whoosh or Xapian.
>
> There is another signal that is executed right before things are
> committed but due to how sessions in SQLAlchemy work you still could not
> change a value on there, so I doubt the usefulness.  Do you think
> another signal might be useful?
>
>
> Regards,
> Armin
>

Re: [flask] Flask-SQLAlchemy Signal Support

From:
Armin Ronacher
Date:
2010-08-03 @ 16:42
Hi,

On 8/3/10 6:08 PM, Dan Jacob wrote:
> Having to loop through all the committed models and check which
> operation seems a bit cumbersome. Would the following be possible:
I would like to keep the application as sender so that you can hook a 
function to a specific instance of an application.  In theory its of 
course possible to send such events but due to how the current signal 
implementation works it does not make much sense to provide model 
specific hooks though.

I guess we need some use cases for signals and models first.  Because 
SQLAlchemy works fundamentally different to Django it becomes quite hard 
to shoot such problems with signals I think.


Regards,
Armin

Re: [flask] Flask-SQLAlchemy Signal Support

From:
Dan Jacob
Date:
2010-08-03 @ 17:13
How about after_insert etc methods in the Model ?

In your MapperExtension:

class _MapperExtension(MapperExtension):

    def after_insert(self, mapper, connection, instance):
         instance.after_insert()
         ....

class Post(Model):
      def after_insert(self):
           search_api.update_posts(self)


On 3 August 2010 17:42, Armin Ronacher <armin.ronacher@active-4.com> wrote:
> Hi,
>
> On 8/3/10 6:08 PM, Dan Jacob wrote:
>> Having to loop through all the committed models and check which
>> operation seems a bit cumbersome. Would the following be possible:
> I would like to keep the application as sender so that you can hook a
> function to a specific instance of an application.  In theory its of
> course possible to send such events but due to how the current signal
> implementation works it does not make much sense to provide model
> specific hooks though.
>
> I guess we need some use cases for signals and models first.  Because
> SQLAlchemy works fundamentally different to Django it becomes quite hard
> to shoot such problems with signals I think.
>
>
> Regards,
> Armin
>

Re: [flask] Flask-SQLAlchemy Signal Support

From:
heww0205
Date:
2010-08-04 @ 13:09
I like this method.

2010/8/4 Dan Jacob <danjac354@gmail.com>

> How about after_insert etc methods in the Model ?
>
> In your MapperExtension:
>
> class _MapperExtension(MapperExtension):
>
>    def after_insert(self, mapper, connection, instance):
>         instance.after_insert()
>         ....
>
> class Post(Model):
>      def after_insert(self):
>           search_api.update_posts(self)
>
>
> On 3 August 2010 17:42, Armin Ronacher <armin.ronacher@active-4.com>
> wrote:
> > Hi,
> >
> > On 8/3/10 6:08 PM, Dan Jacob wrote:
> >> Having to loop through all the committed models and check which
> >> operation seems a bit cumbersome. Would the following be possible:
> > I would like to keep the application as sender so that you can hook a
> > function to a specific instance of an application.  In theory its of
> > course possible to send such events but due to how the current signal
> > implementation works it does not make much sense to provide model
> > specific hooks though.
> >
> > I guess we need some use cases for signals and models first.  Because
> > SQLAlchemy works fundamentally different to Django it becomes quite hard
> > to shoot such problems with signals I think.
> >
> >
> > Regards,
> > Armin
> >
>

Re: [flask] Flask-SQLAlchemy Signal Support

From:
heww0205
Date:
2010-08-03 @ 16:18
Can I got a signal before delete like Django, then I decide whether delete
the data?

2010/8/4 Dan Jacob <danjac354@gmail.com>

> Thanks for adding this.
>
> I'd suggest a couple of changes.
>
> Having to loop through all the committed models and check which
> operation seems a bit cumbersome. Would the following be possible:
>
> from flaskext.sqlalchemy import after_delete
>
> class Post(db.Model):
>     ......
>
> def remove_from_search(sender, instance):
>    search_api.remove(instance)
>
> after_delete.connect(remove_from_search, Post)
>
> This would do pretty much the same as models_committed, but would
> filter the model/operation accordingly.
>
> On 3 August 2010 13:32, Armin Ronacher <armin.ronacher@active-4.com>
> wrote:
> > Hi,
> >
> > Flask-SQLAlchemy just got signal support.  Additionally it's now
> > possible to omit the table name in which case the class name is used.
> >
> > Here a real-worldish example:
> >
> > from flask import Flask
> > from flaskext.sqlalchemy import SQLAlchemy, models_comitted
> >
> > app = Flask(__name__)
> > db = SQLAlchemy(app)
> >
> > class Post(db.Model):
> >     id = db.Column('post_id', db.Integer, primary_key=True)
> >     title = db.Column(db.String(200))
> >     text = db.Column(db.String)
> >
> >     def __init__(self, title, text):
> >         self.title = title
> >         self.text = text
> >
> > def update_post_search_entry(post, operation):
> >     if operation == 'insert':
> >         searchindex.insert(post)
> >     elif operation == 'update':
> >         searchindex.update(post)
> >     elif operation == 'delete':
> >         searchindex.delete(post)
> >
> > def on_models_committed(sender, changes):
> >     for model, change in changes:
> >         if isinstance(model, Post):
> >             update_post_search_entry(model, change)
> >
> > models_committed.connect(on_models_committed, sender=app)
> >
> >
> >
> > The update_post_search_entry here obviously would update the entry in a
> > searchindex for some search backend.  Think Whoosh or Xapian.
> >
> > There is another signal that is executed right before things are
> > committed but due to how sessions in SQLAlchemy work you still could not
> > change a value on there, so I doubt the usefulness.  Do you think
> > another signal might be useful?
> >
> >
> > Regards,
> > Armin
> >
>

Re: [flask] Flask-SQLAlchemy Signal Support

From:
Armin Ronacher
Date:
2010-08-03 @ 16:40
Hi,

On 8/3/10 6:18 PM, heww0205 wrote:
> Can I got a signal before delete like Django, then I decide whether
> delete the data?
That would require some tinkering with how sessions in SQLAlchemy work. 
  I will discuss that with people with proper SQLAlchemy knowledge and 
check if that's possible.


Regards,
Armin

Re: [flask] Flask-SQLAlchemy Signal Support

From:
heww0205
Date:
2010-08-03 @ 15:35
Good news.

2010/8/3 Armin Ronacher <armin.ronacher@active-4.com>

> Hi,
>
> Flask-SQLAlchemy just got signal support.  Additionally it's now
> possible to omit the table name in which case the class name is used.
>
> Here a real-worldish example:
>
> from flask import Flask
> from flaskext.sqlalchemy import SQLAlchemy, models_comitted
>
> app = Flask(__name__)
> db = SQLAlchemy(app)
>
> class Post(db.Model):
>     id = db.Column('post_id', db.Integer, primary_key=True)
>     title = db.Column(db.String(200))
>     text = db.Column(db.String)
>
>     def __init__(self, title, text):
>         self.title = title
>         self.text = text
>
> def update_post_search_entry(post, operation):
>     if operation == 'insert':
>         searchindex.insert(post)
>     elif operation == 'update':
>         searchindex.update(post)
>     elif operation == 'delete':
>         searchindex.delete(post)
>
> def on_models_committed(sender, changes):
>     for model, change in changes:
>         if isinstance(model, Post):
>             update_post_search_entry(model, change)
>
> models_committed.connect(on_models_committed, sender=app)
>
>
>
> The update_post_search_entry here obviously would update the entry in a
> searchindex for some search backend.  Think Whoosh or Xapian.
>
> There is another signal that is executed right before things are
> committed but due to how sessions in SQLAlchemy work you still could not
> change a value on there, so I doubt the usefulness.  Do you think
> another signal might be useful?
>
>
> Regards,
> Armin
>