【问题标题】:Creating a self-referencing M2M relationship in SQLAlchemy (+Flask)在 SQLAlchemy (+Flask) 中创建自引用 M2M 关系
【发布时间】:2013-12-29 21:11:53
【问题描述】:

在尝试学习 Flask 时,我正在构建一个简单的 Twitter 克隆。这将包括用户关注其他用户的能力。我正在尝试通过 SQLAlchemy 设置一个关系数据库来允许这样做。

我想我需要在用户上建立一个自引用的多对多关系。继SQLAlchemy documentation之后,我到达了:

#imports omitted    

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///twitclone.db'
db = SQLAlchemy(app)

Base = declarative_base()

user_to_user = Table("user_to_user", Base.metadata,
    Column("follower_id", Integer, ForeignKey("user.id"), primary_key=True),
    Column("followed_id", Integer, ForeignKey("user.id"), primary_key=True)
)

class User(db.Model):
    __tablename__ = 'user'
    id = Column(Integer, primary_key=True)
    name = Column(String, unique=False)
    handle = Column(String, unique=True)
    password = Column(String, unique=False)
    children = relationship("tweet")
    following = relationship("user",
                    secondary=user_to_user,
                    primaryjoin=id==user_to_user.c.follower_id,
                    secondaryjoin=id==user_to_user.c.followed_id,
                    backref="followed_by"
    )

#Tweet class goes here

db.create_all()

if __name__ == "__main__":
    app.run()

运行此代码会导致创建的数据库没有任何错误消息。然而,将用户连接到用户的整个部分(表格)被简单地省略了。这是User表的定义:

CREATE TABLE user (
    id INTEGER NOT NULL, 
    name VARCHAR, 
    handle VARCHAR, 
    password VARCHAR, 
    PRIMARY KEY (id), 
    UNIQUE (handle)
)

为什么 SQLAlchemy 不为用户创建自引用关系?

注意:我是 Flask 和 SQLAlchemy 的新手,可能在这里遗漏了一些明显的东西。

【问题讨论】:

    标签: sqlalchemy flask self-reference


    【解决方案1】:

    好吧,我似乎混合了两种不同风格的 SQLAlchemy 与 Flask 一起使用:SQLAlchemy 的声明性扩展和 flask-sqlalchemy 扩展。两者的功能相似,不同之处在于烧瓶扩展具有一些优点,例如会话处理。这就是我重写代码以严格使用flask-sqlalchemy的方式。

    from flask import Flask
    from flask.ext.sqlalchemy import SQLAlchemy
    from datetime import datetime
    
    app = Flask(__name__)
    app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///kwek.db'
    db = SQLAlchemy(app)
    
    #Table to handle the self-referencing many-to-many relationship for the User class:
    #First column holds the user who follows, the second the user who is being followed.
    user_to_user = db.Table('user_to_user',
        db.Column("follower_id", db.Integer, db.ForeignKey("user.id"), primary_key=True),
        db.Column("followed_id", db.Integer, db.ForeignKey("user.id"), primary_key=True)
    )
    
    
    class User(db.Model):
        __tablename__ = 'user'
        id = db.Column(db.Integer, primary_key=True)
        name = db.Column(db.String(64), unique=False)
        handle = db.Column(db.String(16), unique=True)
        password = db.Column(db.String, unique=False)
        kweks = db.relationship("Kwek", lazy="dynamic")
        following = db.relationship("User",
                        secondary=user_to_user,
                        primaryjoin=id==user_to_user.c.follower_id,
                        secondaryjoin=id==user_to_user.c.followed_id,
                        backref="followed_by"
        )
    
        def __repr__(self):
            return '<User %r>' % self.name
    
    
    class Kwek(db.Model):
        __tablename__ = 'kwek'
        id = db.Column(db.Integer, primary_key=True)
        content = db.Column(db.String(140), unique=False)
        post_date = db.Column(db.DateTime, default=datetime.now())
        user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
    
        def __repr__(self):
            return '<Kwek %r>' % self.content
    
    if __name__ == "__main__":
        app.run()
    

    【讨论】:

    • 应该没有任何区别(因为 Flask-SQLAlchemy 只是在这里代理 SQLAlchemy 声明式)。以here 为例。
    • 您是对的,尽管 Flask 文档对此并不清楚。我会更新我的答案以反映您的反馈。
    • 太棒了!感谢您返回答案愿意更新它。
    • 如何连接关注者?只是 user.following=(some_other_user.id) 吗?
    猜你喜欢
    • 1970-01-01
    • 2019-01-12
    • 1970-01-01
    • 1970-01-01
    • 2014-01-16
    • 1970-01-01
    • 2020-08-06
    • 1970-01-01
    • 2023-03-17
    相关资源
    最近更新 更多