如何在category_id删除类别时自动将产品设置为默认值?例如1,指向第一个类别.
class Product(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(80))
content = db.Column(db.Text(), unique=True)
category_id = db.Column(db.Integer, db.ForeignKey('category.id'))
atime = db.Column(db.DateTime())
def __init__(self, name, content, category_id):
self.name = name
self.content = content
self.category_id = category_id
self.atime = datetime.now()
def __repr__(self):
return '<Product %r>' % self.id
class Category(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(80))
products = db.relationship('Product', backref='category', cascade="all, delete, delete-orphan")
def __init__(self, *args, **kwargs):
if len(kwargs) > 0:
self.name = kwargs['name']
def __repr__(self):
return '<Category %r>' % self.name
Run Code Online (Sandbox Code Playgroud)
我不想用级联来删除它们!
van*_*van 10
这里需要在业务流程中执行两件事:
我认为最简洁的方法是在删除Category时将其设置category_id为一个NULL值:SET NULL是该子句可能的参照操作之一ON DELETE,您可以将其添加到ForeignKey定义中:
category_id = db.Column(db.Integer, db.ForeignKey('category.id', ondelete='SET NULL'))
Run Code Online (Sandbox Code Playgroud)
以同样的方式使用选项SET DEFAULT,但在这种情况下,您还需要配置列的默认值category_id:category_id = Column(..., server_default=1).请注意,这些实现在不同的RDBMS之间有所不同.
关于cascade选项:您基本上应该cascade="all, delete, delete-orphan"从products关系定义中删除.事实上,你想确保delete, delete-orphan不存在.
话虽如此,您确实需要测试代码以涵盖不同的场景,因为Category对象的两个不同删除可能会产生不同的结果,具体取决于您的RDBMS和SA配置:
# scenario-1: delete in session: SA might set category_id of all chilren Products to None
c1 = session.query(Category).get(1)
session.delete(c1)
session.commit()
# scenario-2: delete without loading an object into the session: SA will perform no additional logic
session.query(Category).filter(Category.id == 2).delete()
session.commit()
Run Code Online (Sandbox Code Playgroud)
希望这一切都指向你正确的方向.像往常一样,使用echo=True或仅通过配置logging模块在您的测试代码中启用SQL日志记录,您将看到SA正在对您的数据库执行的操作.在SQL中没有看到的其他更改是由RDBMS本身根据您的参考操作完成的.