CASCADE 적용안되는것 질문이있습니다.
우선 좋은강의 감사드립니다!
알려주신 방법대로 따라서 하고있다가
"3-15 검색과 정렬" 부분을 실습하던중
제 결과물기준으로
Answer.query.count()
14
Question.query.count()
300
Question.query.join(Answer).count()
10
이렇게 나왔습니다. 그래서 DB Browser를 실행해서 테이블을 봤는데
Answer 테이블에 question_id 부분에 Null 값들이 들어가있는것들을 발견했습니다.
Null이 어디서 생겼는지 생각해보니 "3-10 수정과 삭제" 부분에서 실습을할때 질문을 삭제를 했었습니다.
삭제를 할때 답변을 달려있는 질문도 삭제하였는데 여기서 문제가 발생한것같습니다.
Answer 모델설정할때 question_id 부분에 외래키 설정후 속성값으로
question_id = db.Column(db.Integer, db.ForeignKey('question.id', ondelete='CASCADE'))
ondelete = "CASCADE" 가 적혀있는데도 불구하고
질문이 삭제되어도 답볍은 question_id가 Null로만 변경이되고 삭제는 되지않았습니다.
그래서 SQL 문을 직접 입력하여 질문을 하나 삭제해보았는데
DB에서 직접삭제할때는 CASCADE 가 잘적용이되어 답변도 함께 삭제되었습니다.
python 내에서 db연결에 문제인지 설정중에 뭐가 빠진부분이있는지 감도 안오고
계속 찾다가 못발견해서 여쭤보려고 글을남깁니다 ㅠㅠ
답변주시면 감사하겠습니다.
__init__.py
from flask import Flask
from flask_migrate import Migrate
from flask_sqlalchemy import SQLAlchemy
from sqlalchemy import MetaData
import config
from flaskext.markdown import Markdown
naming_convention = {
"ix": 'ix_%(column_0_label)s',
"uq": "uq_%(table_name)s_%(column_0_name)s",
"ck": "ck_%(table_name)s_%(column_0_name)s",
"fk": "fk_%(table_name)s_%(column_0_name)s_%(referred_table_name)s",
"pk": "pk_%(table_name)s"
}
db = SQLAlchemy(metadata=MetaData(naming_convention=naming_convention))
migrate = Migrate()
# db = SQLAlchemy()
# migrate = Migrate()
def create_app():
app = Flask(__name__)
app.config.from_object(config)
# ORM
db.init_app(app)
if app.config['SQLALCHEMY_DATABASE_URI'].startswith('sqlite'):
migrate.init_app(app, db, render_as_batch=True)
else:
migrate.init_app(app, db)
from . import models
# 블루프린트
from .views import main_view,question_views,answer_views,auth_views,comment_views,vote_views
app.register_blueprint(main_view.bp)
app.register_blueprint(question_views.bp)
app.register_blueprint(answer_views.bp)
app.register_blueprint(auth_views.bp)
app.register_blueprint(comment_views.bp)
app.register_blueprint(vote_views.bp)
# 필터
from .filter import format_datetime
app.jinja_env.filters['datetime'] = format_datetime
# markdown
Markdown(app, extensions=['nl2br','fenced_code'])
return app
이동기 님 1768
M 2020년 9월 18일 11:09 오후
1개의 답변이 있습니다. 1 / 1 Page
안녕하세요.
우선 좋은 질문 감사드립니다.
저도 당연히 될줄 알던것인데 테스트해 보니
질문을 삭제했을때 그에 달린 답변이 삭제가 안되고 question_id 만 Null 로 변경되는 현상을 경험했습니다.
연결된 답변 데이터가 delete가 아닌 update가 실행되는 것 같네요.
하지만 다음처럼 수정하니 update가 아닌 delete가 동작합니다.
class Answer(db.Model):
id = db.Column(db.Integer, primary_key=True)
question_id = db.Column(db.Integer, db.ForeignKey('question.id', ondelete='CASCADE'))
question = db.relationship('Question', backref=db.backref('answer_set', cascade='delete'))
content = db.Column(db.Text(), nullable=False)
create_date = db.Column(db.DateTime(), nullable=False)
user_id = db.Column(db.Integer, db.ForeignKey('user.id', ondelete='CASCADE'), nullable=False)
user = db.relationship('User', backref=db.backref('answer_set'))
modify_date = db.Column(db.DateTime(), nullable=True)
보시면 다음처럼 db.backref 안에 cascade라는 속성을 'delete'로 한번 더 지정해 주면 의도했던데로 답변데이터도 모두 삭제됩니다.
question = db.relationship('Question', backref=db.backref('answer_set', cascade='delete'))
우선 db.ForeignKey('question.id', ondelete='CASCADE'))
에 연결된 CASCADE 는 다음과 같은 테이블 생성 스크립트를 만들어 내는 역할을 합니다.
CREATE TABLE "answer" (
id INTEGER NOT NULL,
question_id INTEGER,
content TEXT NOT NULL,
create_date DATETIME NOT NULL,
user_id INTEGER DEFAULT '1' NOT NULL, modify_date DATETIME,
PRIMARY KEY (id),
CONSTRAINT fk_answer_user_id_user FOREIGN KEY(user_id) REFERENCES user (id) ON DELETE CASCADE,
FOREIGN KEY(question_id) REFERENCES question (id) ON DELETE CASCADE
)
이러한 이유로 쿼리로 직접 삭제할 때는 답변이 함께 삭제되었습니다.
다만, 모델로 삭제할 경우에는 위처럼 수정해 주어야만 제대로 동작하네요.
"점프 투 플라스크"의 내용도 좀 수정이 되어야 겠습니다.
감사합니다.
박응용 님
2020년 9월 19일 12:06 오전