2017-04-05 7 views
1

저는 Flask-SQLAlchemy를 사용하고 있습니다. 나는 연관 테이블을 통해 관계를 공유하는 두 개의 클래스를가집니다. 테이블 중 하나에서 행을 삭제하려고 할 때.플라스크 SQLAlchemy 다 대다 StaleDataError

tags = db.Table('tags', 
    db.Column('tag_id', db.Integer, db.ForeignKey('tag.id')), 
    db.Column('post_id', db.Integer, db.ForeignKey('posts.id')) 
) 

class Post(db.Model): 
    __tablename__ = 'posts' 
    id = db.Column(db.Integer, primary_key=True) 
    title = db.Column(db.String(255)) 
    tags = db.relationship('Tag', secondary=tags, 
         backref=db.backref('posts', lazy='dynamic')) 

    def __init__(self, **kwargs): 
     super(Post, self).__init__(**kwargs) 

    def __repr__(self): 
     return '<title %r>' % self.title 


class Tag(db.Model): 
    __tablename__ = 'tag' 
    id = db.Column(db.Integer, primary_key=True) 
    name = db.Column(db.String(120), unique=True) 

여기에 내가 삭제를 실행 코드는 다음과 같습니다 : 여기

sqlalchemy.orm.exc.StaleDataError 
StaleDataError: DELETE statement on table 'tags' expected to delete 1 row(s); Only 2 were matched. 

내 모델입니다 : 나는 다음과 같은 오류가 나는 스트라이프 다운 버전을 시도

def remove_tag(tag_id): 
    tag = Tag.query.get(tag_id) 
    for post in tag.posts: 
     p = Post.query.get(post.id) 
     p.tags.remove(tag) 
db.session.delete(tag) 
db.session.commit() 

독립 실행 형 테스트, db 및 환경에서이 코드 외부,이 응용 프로그램 외부. 그리고 예상대로 태그와 관련 테이블 행을 제거합니다.

내가 알고 싶은 것이 가능하다면 :

나는 StaleDataError의 상황에서 거지 어떻게
  • ?
  • .all()에 대한 내 쿼리에서 여러 용도가 표시되지 않는데 왜 둘 이상의 행과 일치합니까?
  • 어떻게 이런 일이 발생하지 않도록 할 수 있습니까?

미리 도움을 청하십시오.

보다도, 에드워드

+0

예제에서 들여 쓰기를 수정했지만 오류가있는 것 같지만 'remove_tag()'을 그대로 둡니다. 확인해 주시겠습니까? –

답변

0

을 일으켰다!

How did I get in the situation of a StaleDataError ?

내 편집 게시물 페이지를 테스트 할 때 데이터베이스에 동일한 게시물의 POST를 많이 수행했습니다.

Why does it match more than one row, when my query to .all() doesn't show multiple uses?

테스트 결과 연관 테이블에 여러 항목이 생성되었습니다. 즉, 나는 (tag.id= 1, post.id=1)을 여러 번 사용했다.

How can I prevent this from happening?

DB에 여러 항목을 중지하려면 고유 한 제약 조건을 연결 테이블에 추가하십시오. 나는 또한 여러 항목을 중지하는 내보기에 체크를 추가했습니다.

tags = db.Table(
    'tags', 
    db.Column('tag_id', db.Integer, db.ForeignKey('tag.id')), 
    db.Column('post_id', db.Integer, db.ForeignKey('posts.id')), 
    db.UniqueConstraint('tag_id', 'post_id', name='UC_tag_id_post_id') 
) 

DB를 마이그레이션하십시오.

SQlite 및 Alembic을 사용하는 경우 "SQLite 언어의 제약 조건에 대한 ALTER 지원이 없습니다"라는 오류가 발생할 가능성이 큽니다. 이 문제에 대한 자세한 내용은 here을 참조하십시오.

요약하면 개발 데이터베이스 인 경우 DB를 삭제하는 것이 더 쉽습니다. 프로덕션 환경에서 데이터 마이그레이션을 고려하고 다른 엔진으로 전환해야합니다.