Python Peewee 中相同 table 的外键

Foreign key to the same table in Python Peewee

我在 Python 中为 sqlite 使用 ORM peewee。我想用字段 parent_id 创建 table Item ,它将成为 Item:

的外键
from peewee import *

db = SqliteDatabase("data.db")

class Item(Model):
    id = AutoField()
    parent_id = ForeignKeyField(Item, null = True)

    class Meta:
        database = db

db.create_tables([Item])

但是由于循环外键出现错误:

NameError: free variable 'Item' referenced before assignment in enclosing scope

对于这种情况,peewee中有DeferredForeignKey

from peewee import *

db = SqliteDatabase("data.db")

class Item(Model):
    id = AutoField()
    parent_id = DeferredForeignKey("Item", null = True)

    class Meta:
        database = db

db.create_tables([Item])
Item._schema.create_foreign_key(Item.parent_id)

不幸的是,sqlite中没有ADD CONSTRAINT,所以又出现了一个错误:

peewee.OperationalError: near "CONSTRAINT": syntax error

有什么方法可以使用 peewee 在 sqlite 中创建循环外键,或者我必须使用普通整数而不是外键或使用本机 SQL 而不是 ORM?

我找到了解决方案。可以在 Meta class:

添加自定义约束
from peewee import *

db = SqliteDatabase("data.db", pragmas = {"foreign_keys": "on"})

class Item(Model):
    id = AutoField()
    parent_id = IntegerField()

    class Meta:
        database = db
        constraints = [
            SQL("FOREIGN KEY(parent_id) REFERENCES items(id)")
        ]

db.create_tables([Item])

这个记录的很清楚:http://docs.peewee-orm.com/en/latest/peewee/models.html#self-referential-foreign-keys

您只需将 'self' 作为标识符:

class Item(Model):
    id = AutoField()
    parent = ForeignKeyField('self', backref='children', null=True)

    class Meta:
        database = db

您不需要弄乱任何延迟键或任何东西。