代码之家  ›  专栏  ›  技术社区  ›  8-Bit Borges

Flask SQLAlchemy:IntegrityError:(由于查询调用了autoflush而引发)在for循环中

  •  0
  • 8-Bit Borges  · 技术社区  · 6 年前

    data = zip(playlists, artists, tracks, uris)
    
    count=0
    for d in data:
        # check if playlist is new to database
        if db.session.query(Playlist).filter_by(title=d[0]).count() < 1:
            # ADD FIRST TRACK
            track = Track(title=d[2],
                          artist=d[1],
                          uri=d[3],
                          track_id=1)
    
            db.session.add(track)
    
            playlist = Playlist(title=d[0], 
                                user=User.query.get(1))
    
            playlist.tracks.append(track)
            db.session.add(playlist)
    
        else:               
            # ADD TRACKS
            track = Track(title=d[2],
                          artist=d[1],
                          uri=d[3],
                          track_id=count+1)
    
            db.session.add(track)
    
            # look for existent playlist
            pl = Playlist.query.filter_by(title=d[0]).first()
    
            print ('EXISTENT PLAYLIST', pl)
    
            # add tracks to existent playlist
            pl.tracks.append(track)
    
        count+=1
        db.session.commit()
    

    这些是我的模型:

    class Playlist(db.Model):
        """
        Model for storing playlist information belonging to a specific user
        """
        __tablename__ = 'playlist'
    
        id = db.Column(db.Integer, primary_key=True)
        title = db.Column(db.String(50), unique=True)
        user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
    
        user = db.relationship('User',
                    backref=db.backref('playlists', lazy='dynamic'))
    
        tracks = db.relationship('Track', secondary=tracks,
                backref=db.backref('playlists', lazy='dynamic'))
    
    
        def __init__(self, title, user):
            self.title = title
            self.user = user
    
    
        def __repr__(self):
            return '<Playlist %r>' % (self.title)
    
    
        @property
        def serialize(self):
           """Return object data in easily serializeable format"""
           return {
               'id' : self.id,
               'title': self.title,
               'user': self.user.serialize,
               'tracks': [ item.serialize for item in self.tracks]
           }
    
    
    
    class Track(db.Model):
        """
        Model for storing track information
        """
        id = db.Column(db.Integer, primary_key=True)
        title = db.Column(db.String(140))
        artist = db.Column(db.String(140))
        uri = db.Column(db.String(50), unique=True)
        track_id = db.Column(db.String(140), unique=True)
    
    
        def __init__(self, title, artist, uri, track_id):
            self.title = title
            self.artist = artist
            self.uri = uri
            self.track_id = track_id
    
    
        def __repr__(self):
            return '<Track %r>, <Artist %r>' % (self.title, self.artist)
    
    
        @property
        def serialize(self):
           """Return object data in easily serializeable format"""
           return {
               'id' : self.id,
               'title': self.title,
               'artist': self.artist,
               'uri': self.uri,
               'track_id': self.track_id
           }
    

    一切正常,所有曲目都已创建并添加到第一个播放列表中,但只要转到第二个播放列表,就会得到以下回溯:

    完整回溯:

    127.0.0.1 - - [13/Aug/2018 17:43:29] "POST /login HTTP/1.1" 500 -
    Traceback (most recent call last):
      File "/usr/local/lib/python2.7/site-packages/flask/app.py", line 1836, in __call__
        return self.wsgi_app(environ, start_response)
      File "/usr/local/lib/python2.7/site-packages/flask/app.py", line 1820, in wsgi_app
        response = self.make_response(self.handle_exception(e))
      File "/usr/local/lib/python2.7/site-packages/flask/app.py", line 1403, in handle_exception
        reraise(exc_type, exc_value, tb)
      File "/usr/local/lib/python2.7/site-packages/flask/app.py", line 1817, in wsgi_app
        response = self.full_dispatch_request()
      File "/usr/local/lib/python2.7/site-packages/flask/app.py", line 1477, in full_dispatch_request
        rv = self.handle_user_exception(e)
      File "/usr/local/lib/python2.7/site-packages/flask/app.py", line 1381, in handle_user_exception
        reraise(exc_type, exc_value, tb)
      File "/usr/local/lib/python2.7/site-packages/flask/app.py", line 1475, in full_dispatch_request
        rv = self.dispatch_request()
      File "/usr/local/lib/python2.7/site-packages/flask/app.py", line 1461, in dispatch_request
        return self.view_functions[rule.endpoint](**req.view_args)
      File "/Users/vitorpatalano/Documents/Code/Apps/myapp/app.py", line 459, in do_admin_login
        if db.session.query(Playlist).filter_by(title=d[0]).count() < 1:
      File "/Users/vitorpatalano/anaconda2/lib/python2.7/site-packages/sqlalchemy/orm/query.py", line 3089, in count
        return self.from_self(col).scalar()
      File "/Users/vitorpatalano/anaconda2/lib/python2.7/site-packages/sqlalchemy/orm/query.py", line 2843, in scalar
        ret = self.one()
      File "/Users/vitorpatalano/anaconda2/lib/python2.7/site-packages/sqlalchemy/orm/query.py", line 2814, in one
        ret = self.one_or_none()
      File "/Users/vitorpatalano/anaconda2/lib/python2.7/site-packages/sqlalchemy/orm/query.py", line 2784, in one_or_none
        ret = list(self)
      File "/Users/vitorpatalano/anaconda2/lib/python2.7/site-packages/sqlalchemy/orm/query.py", line 2854, in __iter__
        self.session._autoflush()
      File "/Users/vitorpatalano/anaconda2/lib/python2.7/site-packages/sqlalchemy/orm/session.py", line 1407, in _autoflush
        util.raise_from_cause(e)
      File "/Users/vitorpatalano/anaconda2/lib/python2.7/site-packages/sqlalchemy/util/compat.py", line 203, in raise_from_cause
        reraise(type(exception), exception, tb=exc_tb, cause=cause)
      File "/Users/vitorpatalano/anaconda2/lib/python2.7/site-packages/sqlalchemy/orm/session.py", line 1397, in _autoflush
        self.flush()
      File "/Users/vitorpatalano/anaconda2/lib/python2.7/site-packages/sqlalchemy/orm/session.py", line 2171, in flush
        self._flush(objects)
      File "/Users/vitorpatalano/anaconda2/lib/python2.7/site-packages/sqlalchemy/orm/session.py", line 2291, in _flush
        transaction.rollback(_capture_exception=True)
      File "/Users/vitorpatalano/anaconda2/lib/python2.7/site-packages/sqlalchemy/util/langhelpers.py", line 66, in __exit__
        compat.reraise(exc_type, exc_value, exc_tb)
      File "/Users/vitorpatalano/anaconda2/lib/python2.7/site-packages/sqlalchemy/orm/session.py", line 2255, in _flush
        flush_context.execute()
      File "/Users/vitorpatalano/anaconda2/lib/python2.7/site-packages/sqlalchemy/orm/unitofwork.py", line 389, in execute
        rec.execute(self)
      File "/Users/vitorpatalano/anaconda2/lib/python2.7/site-packages/sqlalchemy/orm/unitofwork.py", line 548, in execute
        uow
      File "/Users/vitorpatalano/anaconda2/lib/python2.7/site-packages/sqlalchemy/orm/persistence.py", line 181, in save_obj
        mapper, table, insert)
      File "/Users/vitorpatalano/anaconda2/lib/python2.7/site-packages/sqlalchemy/orm/persistence.py", line 835, in _emit_insert_statements
        execute(statement, params)
      File "/Users/vitorpatalano/anaconda2/lib/python2.7/site-packages/sqlalchemy/engine/base.py", line 945, in execute
        return meth(self, multiparams, params)
      File "/Users/vitorpatalano/anaconda2/lib/python2.7/site-packages/sqlalchemy/sql/elements.py", line 263, in _execute_on_connection
        return connection._execute_clauseelement(self, multiparams, params)
      File "/Users/vitorpatalano/anaconda2/lib/python2.7/site-packages/sqlalchemy/engine/base.py", line 1053, in _execute_clauseelement
        compiled_sql, distilled_params
      File "/Users/vitorpatalano/anaconda2/lib/python2.7/site-packages/sqlalchemy/engine/base.py", line 1189, in _execute_context
        context)
      File "/Users/vitorpatalano/anaconda2/lib/python2.7/site-packages/sqlalchemy/engine/base.py", line 1402, in _handle_dbapi_exception
        exc_info
      File "/Users/vitorpatalano/anaconda2/lib/python2.7/site-packages/sqlalchemy/util/compat.py", line 203, in raise_from_cause
        reraise(type(exception), exception, tb=exc_tb, cause=cause)
      File "/Users/vitorpatalano/anaconda2/lib/python2.7/site-packages/sqlalchemy/engine/base.py", line 1182, in _execute_context
        context)
      File "/Users/vitorpatalano/anaconda2/lib/python2.7/site-packages/sqlalchemy/engine/default.py", line 470, in do_execute
        cursor.execute(statement, parameters)
    **IntegrityError: (raised as a result of Query-invoked autoflush; consider using a session.no_autoflush block if this flush is occurring prematurely) (sqlite3.IntegrityError) UNIQUE constraint failed: track.track_id [SQL: u'INSERT INTO track (title, artist, uri, track_id) VALUES (?, ?, ?, ?)'] [parameters: ('No Intention', 'Dirty Projectors', 'spotify:track:4Ozug40zUcMiE2s1neJQRb', 1)]**
    127.0.0.1 - - [13/Aug/2018 17:43:29] "GET /login?__debugger__=yes&cmd=resource&f=style.css HTTP/1.1" 200 -
    127.0.0.1 - - [13/Aug/2018 17:43:29] "GET /login?__debugger__=yes&cmd=resource&f=debugger.js HTTP/1.1" 200 -
    127.0.0.1 - - [13/Aug/2018 17:43:29] "GET /login?__debugger__=yes&cmd=resource&f=jquery.js HTTP/1.1" 200 -
    127.0.0.1 - - [13/Aug/2018 17:43:29] "GET /login?__debugger__=yes&cmd=resource&f=ubuntu.ttf HTTP/1.1" 200 -
    127.0.0.1 - - [13/Aug/2018 17:43:29] "GET /login?__debugger__=yes&cmd=resource&f=console.png HTTP/1.1" 200 -
    

    我错过了什么?

    1 回复  |  直到 6 年前
        1
  •  1
  •   shifloni    6 年前

    从代码中不可能知道您试图插入的数据是什么样子的,但是从读取模型定义和错误来看,您违反了跟踪表中的唯一约束。你的足迹 uri track_id 属性具有唯一约束,这意味着您只能有一个唯一轨迹 乌里 还有一个 在整个数据库中。用户可能在两个不同的播放列表中拥有相同的曲目吗?如果这是可能的,那么您应该在上删除跟踪表定义中的唯一约束 曲目id 看看这个错误是否会消失。