Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/334.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何在删除时将外键设置为默认值?_Python_Sqlalchemy - Fatal编程技术网

Python 如何在删除时将外键设置为默认值?

Python 如何在删除时将外键设置为默认值?,python,sqlalchemy,Python,Sqlalchemy,删除类别时,如何将产品类别\u 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(

删除类别时,如何将产品
类别\u 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
类产品(db.Model):
id=db.Column(db.Integer,主键=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())
定义初始化(自我、名称、内容、类别id):
self.name=名称
self.content=内容
self.category\u id=category\u id
self.atime=datetime.now()
定义报告(自我):
返回“%self.id”
类别(数据库模型):
id=db.Column(db.Integer,主键=True)
name=db.Column(db.String(80))
products=db.relationship('Product',backref='category',cascade='all,delete,delete orphan〕)
定义初始化(self,*args,**kwargs):
如果len(kwargs)>0:
self.name=kwargs['name']
定义报告(自我):
返回“%self.name”

我不想用cascade删除它们

这里有两件事需要在编排中执行:

  • 使用适当的引用操作定义外键
  • 配置SA关系的级联选项
  • 我认为最干净的方法是在其类别被删除时,将
    category\u id
    设置为
    NULL
    值:
    set NULL
    ON DELETE
    子句中可能的一种,您可以将其添加到定义中:

    category_id = db.Column(db.Integer, db.ForeignKey('category.id', ondelete='SET NULL'))
    
    同样,您可以使用一个选项,但在这种情况下,您还需要为列
    category\u id
    配置默认值:
    category\u id=column(…,server\u default=1)
    。请注意,不同RDBMS之间的这些实现是不同的

    至于
    cascade
    选项:您基本上应该从您的
    产品
    关系定义中删除
    cascade=“all,delete,delete orphan”
    。事实上,您希望确保不存在
    delete,delete orphan

    话虽如此,您确实需要测试代码以覆盖不同的场景,因为根据您的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()
    
    希望所有这些都为你指明了正确的方向。和往常一样,使用或仅通过配置
    logging
    模块在测试代码中启用SQL日志记录,您将看到SA对数据库做了什么。您在SQL中没有看到的其他更改是由RDBMS本身根据您的引用操作完成的