什么时候使用 SQL 外键使用 peewee?

When to use SQL Foreign key using peewee?

我目前正在使用 PeeWee 和 Python,我已经成功地创建了一个不错的初学者

CREATE TABLE stores (
    id SERIAL PRIMARY KEY,
    store_name TEXT
);


CREATE TABLE products (
    id SERIAL, 
    store_id INTEGER NOT NULL,
    title TEXT,
    image TEXT,
    url TEXT UNIQUE, 
    added_date timestamp without time zone NOT NULL DEFAULT NOW(),
    PRIMARY KEY(id, store_id)
);


ALTER TABLE products
ADD  CONSTRAINT "FK_products_stores" FOREIGN KEY ("store_id")
        REFERENCES stores (id) MATCH SIMPLE
        ON UPDATE NO ACTION
        ON DELETE RESTRICT;

已通过以下代码转换为 peewee:

# ------------------------------------------------------------------------------- #
class Stores(Model):
    id = IntegerField(column_name='id')
    store_name = TextField(column_name='store_name')

    class Meta:
        database = postgres_pool
        db_table = "stores"

    @classmethod
    def get_all(cls):
        try:
            return cls.select(cls.id, cls.store_name).order_by(cls.store)
        except Stores.IntegrityError:
            return None




   # ------------------------------------------------------------------------------- #
class Products(Model):
    id = IntegerField(column_name='id')
    store_id = TextField(column_name='store_id')
    title = TextField(column_name='title')
    url = TextField(column_name='url')
    image = TextField(column_name='image')
    store = ForeignKeyField(Stores, backref='products')

    class Meta:
        database = postgres_pool
        db_table = "products"

    @classmethod
    def get_all_products(cls, given_id):
        try:
            return cls.select().where(cls.store_id == given_id)
        except Stores.IntegrityError:
            return None

    @classmethod
    def add_product(cls, pageData, store_id):
        """
        INSERT
        INTO
        public.products(store_id, title, image, url)
        VALUES((SELECT id FROM stores WHERE store_name = 'footish'), 'Teva Flatform Universal Pride',
               'https://www.footish.se/sneakers/teva-flatform-universal-pride-t51116376',
               'https://www.footish.se/pub_images/large/teva-flatform-universal-pride-t1116376-p77148.jpg?timestamp=1623417840')
        """
        try:
            return cls.insert(
                store_id=store_id,
                title=pageData.title,
                url=pageData.url,
                image=pageData.image,
            ).execute()
        except Products.DoesNotExist:
            return None
        except peewee.IntegrityError as err:
            print(f"error: {err}")
            return None

我的想法是,当我启动我的应用程序时,我会有一个常量变量,store_id 已经设置,例如1。有了它,查询的执行速度会更快,因为我不需要另一个 select 来通过 store_name 获得 store_id。但是看看我的代码。我有一个字段是:store = ForeignKeyField(Stores, backref='products') 我开始思考在我的应用程序中我需要什么。

我知道我的 ALTER 查询确实有一个 FK,但在我编写的应用程序中,我完全看不出我需要输入外键的原因,但我需要一些帮助了解更多为什么以及如何在我的应用程序中使用值“存储”。可能是我想的那样,我可能根本不需要它?

你好! 通过阅读你关于通过常量变量“更快地执行查询”的最初想法,首先想到的是总是有这样的麻烦手动编辑变量。这是一种糟糕的做法,不是您想要在专业应用程序上做的事情。要获得您应该使用的值,我建议 运行 以编程方式查询并使用 SQL 的 MAX() 函数获取 id 的最高值。

至于外键,您 没有 使用它,但在重要的时候它可能是个好习惯。在这种情况下,查看您的 FK 约束:它有一个 ON DELETE RESTRICT 语句,如果它有数据被用作外部数据,它会取消对父 table 的任何删除操作键入另一个 table。这将需要转到另一个 table,即具有外键的那个,并删除与前一个 table 上的行相关的每一行,然后才能删除它。

一般来说,如果您有两个 table 的信息以 any 方式链接,我强烈建议您使用密钥。它增加了组织性,如果添加了适当的约束,它会增加外部用户的可读性并减少错误。

在使用您提到的 store 时,您可能希望 API return 所有产品都与单个商店相关。或除特定产品之外的所有产品。

由于没有完全自信我理解了这个问题,所以我试图让事情变得简单。希望对您有所帮助。