sqlite sqlalchemy插入前检查外键引用数据是否存在?

ldioqlga  于 2023-01-21  发布在  SQLite
关注(0)|答案(1)|浏览(179)

我是sqlalchemy和fastAPI的新手。我想知道有什么方法可以在插入引用数据之前自动检查引用数据。例如,我想在添加新的配置文件之前确保profile.user_id存在,但我不想自己做这件事。这可能吗?下面是我的表设置。

class User(Base):
    __tablename__ = "user"

    id = Column("id", Integer, primary_key=True, autoincrement=True)
    email = Column(String, unique=True, nullable=False)
    hashed_password = Column(String, nullable=False)
    create_time = Column(DateTime, nullable=False, default=func.now())
    login_time = Column(DateTime, nullable=False, default=func.now())

class Profile(Base):
    __tablename__ = "user_profile"
    id = Column(Integer, primary_key=True, autoincrement=True)
    user_id = Column(Integer, ForeignKey("user.id"), nullable=False)
    name = Column(String, )
    age = Column(Integer)
    country = Column(Integer)
    photo = Column(String, )
7xllpg7q

7xllpg7q1#

Map类中缺少的是relationship
在ORM中,这些关系负责确保外键存在,并使创建关系变得更加容易。
另外,如果你想在SQL端设置一个默认值(因为你使用了default=func.now()),你应该使用server_default=func.now()关键字参数,否则,使用python端的等价物default=datetime.utcnow()
最后,如果关系是一对一关系,请在User.profiles关系中使用uselist=False关键字参数(最好也将其重命名为User.profile)。

from datetime import datetime

from sqlalchemy import (
    Column,
    DateTime,
    ForeignKey,
    Integer,
    String,
    create_engine,
)
from sqlalchemy.orm import Session, declarative_base, relationship

Base = declarative_base()

class User(Base):
    __tablename__ = "user"
    id = Column("id", Integer, primary_key=True, autoincrement=True)
    email = Column(String, unique=True, nullable=False)
    hashed_password = Column(String, nullable=False)
    create_time = Column(DateTime, nullable=False, default=datetime.utcnow())
    login_time = Column(DateTime, nullable=False, default=datetime.utcnow())
    profiles = relationship(
        "Profile", back_populates="user"
    )  # add uselist=False if one-to-one

class Profile(Base):
    __tablename__ = "user_profile"
    id = Column(Integer, primary_key=True, autoincrement=True)
    user_id = Column(Integer, ForeignKey("user.id"), nullable=False)
    name = Column(String)
    age = Column(Integer)
    country = Column(Integer)
    photo = Column(String)
    user = relationship("User", back_populates="profiles")

engine = create_engine("sqlite://", echo=True, future=True)

Base.metadata.create_all(engine)

with Session(engine) as session:

    ljmc = User(email="ljmc@stack.overflow", hashed_password="00ab")
    ljmc_profile = Profile(name="ljmc")

    ljmc_profile.user = ljmc

    session.add(ljmc)
    session.flush()

这会发出:

CREATE TABLE user (
        id INTEGER NOT NULL, 
        email VARCHAR NOT NULL, 
        hashed_password VARCHAR NOT NULL, 
        create_time DATETIME NOT NULL, 
        login_time DATETIME NOT NULL, 
        PRIMARY KEY (id), 
        UNIQUE (email)
)
CREATE TABLE user_profile (
        id INTEGER NOT NULL, 
        user_id INTEGER NOT NULL, 
        name VARCHAR, 
        age INTEGER, 
        country INTEGER, 
        photo VARCHAR, 
        PRIMARY KEY (id), 
        FOREIGN KEY(user_id) REFERENCES user (id)
)
INSERT INTO user (email, hashed_password, create_time, login_time) VALUES ('ljmc@stack.overflow', '00ab', '2023-01-17 10:11:48.250845', '2023-01-17 10:11:48.250959')
INSERT INTO user_profile (user_id, name, age, country, photo) VALUES (1, 'ljmc', None, None, None)

相关问题