簡體   English   中英

燒瓶外鍵約束

[英]Flask Foreign Key Constraint

我在Flask中有一個外鍵問題。 我的模型如下:

模型

class User(db.Model):

    __tablename__ = "users"
    __table_args__ = {'extend_existing': True}
    user_id = db.Column(db.BigInteger, primary_key=True)
    # EDIT
    alerts = db.relationship('Alert', backref='user', lazy='dynamic')

    def __init__(self, user_id):
        self.user_id = user_id


class Alert(db.Model):

    __tablename__ = 'alert'
    __table_args__ = {'extend_existing': True}
    alert_id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    user_id = db.Column(db.BigInteger, db.ForeignKey('users.user_id'), nullable=False)
    name = db.Column(db.String(ALERT_NAME_MAX_SIZE), nullable=False)

    def __init__(self, user_id, name):
        self.user_id = user_id
        self.name = name

我可以添加一些用戶,例如

a = User(16)
b = User(17)
db.session.add(a)
db.session.add(b)
db.session.commit()

和一些警報:

c = Alert(16, 'test')
d = Alert(17, 'name_test')
db.session.add(c)
db.session.add(d)
db.session.commit()

我的外鍵有兩個問題:首先,當我嘗試修改user_id警報時,即使user_id不在數據庫中,我也可以做到這一點

 alert = Alert.query.get(1)
 alert.user_id = 1222 # not in the database
 db.session.commit()

而且我能夠使用不在數據庫中的user_id創建警報:

r = Alert(16223, 'test')
db.session.add(r)

我不明白為什么他們沒有關系約束。 謝謝,

所以我找到了解決這個stackoverflow問題的方法 ,找到了強制外鍵約束的方法。

我只是將其添加到__init__.pymodels.pymodels.py任何更改

@event.listens_for(Engine, "connect")
    def _set_sqlite_pragma(dbapi_connection, connection_record):
         if isinstance(dbapi_connection, SQLite3Connection):
              cursor = dbapi_connection.cursor()
              cursor.execute("PRAGMA foreign_keys=ON;")
              cursor.close()

初始化Alert類的代碼中有錯誤。 初始化Alert時,應使用backref變量(“ user”)代替user_id。 下面的代碼應該工作。

class User(db.Model):

    __tablename__ = "user"
    __table_args__ = {'extend_existing': True}
    user_id = db.Column(db.BigInteger, primary_key=True)
    alerts = db.relationship('Alert', backref='user', lazy='dynamic')

    def __init__(self, user_id):
        self.user_id = user_id


class Alert(db.Model):

    __tablename__ = 'alert'
    alert_id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    user_id = db.Column(db.BigInteger, db.ForeignKey('user.user_id'), nullable=False)
    name = db.Column(db.String(ALERT_NAME_MAX_SIZE), nullable=False)

    def __init__(self, user, name):
        self.user = user
        self.name = name

它的工作原理如下:

>>> a = User(7)
>>> db.session.add(a)
>>> db.session.commit()
>>> b = Alert(a, 'test')
>>> db.session.add(b)
>>> db.session.commit()
>>> alert = Alert.query.get(1)
>>> alert.user_id
7
>>> alert.user
<app.User object at 0x1045cb910>
>>> alert.user.user_id
7

它不允許您分配變量,例如d = Alert(88, 'trdft')

我認為您應該閱讀Flask SqlAlchemy的一對多關系以了解更多詳細信息。

如果您使用的是SQLite,則默認情況下不強制使用外鍵約束。 有關如何啟用此功能,請參閱文檔中的啟用外鍵支持

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM