Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SQLALCHEMY: how to use @events.listens_for in flask_sqlalchemy-SQLalchemy

i need some help in automating some tasks in sqlalchemy. when a new user registers on my website i need 5 personnel to be added.

i would like to use the sqlalchemy events because if i can get it to work it will come in handy later for other automations.

i am following Mr Miguel Grinberg's Tutorial on how to make a flask application and to define my models (db.Model not Base).

i read that to use @event.listens_for(User.__table__, "after_insert") i have to use a declarative base. is there a way around this? My model structure involves close to 15 tables!

  class User(db.Model):
        __tablename__ = "user"
        id = db.Column(db.Integer, primary_key=True, autoincrement=True)
        email = db.Column(db.String(64), unique=True, index=True)
        username = db.Column(db.String(64), unique=True, index=True)
        password_hash = db.Column(db.String(128))
        store = db.relationship('Store', uselist=False, backref="user")



@event.listens_for(User.__table__, "after_insert")
def add_personnel(*args, **kwargs):
    for i in range(5):
        db.session.add(Personnel,store_id = User.query.last().id)
    db.session.commit()
    return None

class Personnel(db.Model):
    __tablename__ = "personnel"
    id = db.Column(db.Integer, primary_key=True)
    store_id = db.Column(db.Integer, db.ForeignKey('store.id'))
    first_name = db.Column(db.String(64))
    last_name = db.Column(db.String(64))
    username = db.Column(db.String(64))
    cell_phone = db.Column(db.Integer)
    pin_number = db.Column(db.Integer)
    email = db.Column(db.String(64))
    orders = db.relationship("Order", backref='personnel', lazy='dynamic')

**TRACEBACK**



    Traceback (most recent 
    call last):
      File "manage.py", line 3, in <module>
        from app.models import User
      File "/home/#######/PycharmProjects/#######/app/models.py", line 62, in <module>
        @event.listens_for(User.__table__, "after_insert")
      File "/home/#######/PycharmProjects/#######//venv/local/lib/python2.7/site-packages/sqlalchemy/event/api.py", line 124, in decorate
        listen(target, identifier, fn, *args, **kw)
      File "/home/#######/PycharmProjects/#######/venv/local/lib/python2.7/site-packages/sqlalchemy/event/api.py", line 89, in listen
        _event_key(target, identifier, fn).listen(*args, **kw)
      File "/home/#######/PycharmProjects/#######/venv/local/lib/python2.7/site-packages/sqlalchemy/event/registry.py", line 194, in listen
        dispatch_collection = getattr(target.dispatch, identifier)
      File "/home/#######/PycharmProjects/#######/venv/local/lib/python2.7/site-packages/sqlalchemy/event/base.py", line 95, in __getattr__
        raise AttributeError(name)
    AttributeError: after_insert
like image 454
George Pamfilis Avatar asked Dec 20 '16 18:12

George Pamfilis


2 Answers

I got i working just like this using the connection from the arguments.

@db.event.listens_for(Order, "after_insert")
def insert_order_to_printer(mapper, connection, target):
    po = PrinterOrder.__table__
    connection.execute(po.insert().values(store_id=target.store_id, order_id=target.id, scenario=target.order_type))

where order is:

class Order(db.Model):
    #stuff
like image 154
George Pamfilis Avatar answered Oct 26 '22 09:10

George Pamfilis


You actually can do this, just by typing @event.listens_for(User, "after_insert") as described in this answer.

Note that you need to use SQLAlchemy Connection instead of sessions as you used in your sample event. Check this answer, it has great examples of processing database inserts.

like image 29
Sergey Shubin Avatar answered Oct 26 '22 09:10

Sergey Shubin