在尝试学习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的新手,可能会遗漏一些明显的东西。
答案 0 :(得分:7)
好吧,似乎我混淆了两种不同风格的使用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()