Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/postgresql/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
sqlalchemy对称多对一友谊_Sql_Postgresql_Sqlalchemy_Flask Sqlalchemy - Fatal编程技术网

sqlalchemy对称多对一友谊

sqlalchemy对称多对一友谊,sql,postgresql,sqlalchemy,flask-sqlalchemy,Sql,Postgresql,Sqlalchemy,Flask Sqlalchemy,我正在尝试使用SQLAlchemy ORM建立友谊模型。我试图建立的关系是对称的。与Facebook类似,如果用户a要添加用户b,则用户b必须批准该友谊请求。我目前的模式如下 class User(db.Model): __tablename__ = 'User' id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(35), unique=False) username = db.Colu

我正在尝试使用SQLAlchemy ORM建立友谊模型。我试图建立的关系是对称的。与Facebook类似,如果用户a要添加用户b,则用户b必须批准该友谊请求。我目前的模式如下

class User(db.Model):
  __tablename__ = 'User'
  id = db.Column(db.Integer, primary_key=True)
  name = db.Column(db.String(35), unique=False)
  username = db.Column(db.String(25), index=True, unique=True)
  password = db.Column(db.String(35), unique=False)
  email = db.Column(db.String(35), unique=True)
  phone_number = db.Column(db.String(22))

  # define relationships
  requester = db.relationship('Relationship', foreign_keys='Relationship.requesting_user', backref='requester')
  receiver = db.relationship('Relationship', foreign_keys='Relationship.receiving_user', backref='received')

  def __repr__(self):
    return '<User %r>' % (self.username)


class Relationship(db.Model):
  __tablename__ = 'Relationship'
  id = db.Column(db.Integer, primary_key=True)
  requesting_user = db.Column(db.Integer, db.ForeignKey('User.id'))
  receiving_user = db.Column(db.Integer, db.ForeignKey("User.id"))
  status = db.Column(db.Integer)
  __table_args__ = (db.UniqueConstraint('receiving_user', 'requesting_user', name='_receiving_user_uc'), )
类用户(db.Model):
__tablename_uu='User'
id=db.Column(db.Integer,主键=True)
name=db.Column(db.String(35),unique=False)
username=db.Column(db.String(25),index=True,unique=True)
password=db.Column(db.String(35),unique=False)
email=db.Column(db.String(35),unique=True)
phone_number=db.Column(db.String(22))
#定义关系
requester=db.relationship('relationship',foreign_key='relationship.requesting_user',backref='requester')
receiver=db.relationship('relationship',foreign_key='relationship.receiving_user',backref='received')
定义报告(自我):
返回“”%(self.username)
类关系(db.Model):
__tablename_uu='Relationship'
id=db.Column(db.Integer,主键=True)
正在请求_user=db.Column(db.Integer,db.ForeignKey('user.id'))
接收_user=db.Column(db.Integer,db.ForeignKey(“user.id”))
status=db.Column(db.Integer)
__表_args_uuuu=(db.UniqueConstraint('receiving_user','requising_user',name='u receiving_user_uc'))

这个模型是可行的,但是,我认为它没有被正确地建模。是否要求我使用状态?我假设它可以建模,这样每个朋友关系都有自己的条目。目前,用户可以与其他用户发起好友请求。当其他用户批准请求时,状态更改为已接受。我已经研究了一些关联表,但不太确定它们将如何在这样的模型中发挥作用。非常感谢您对我当前的模型以及如何改进的任何建议。

除此之外,您可能还想了解。关联代理告诉SQLAlchemy,您有一个多对多关系,该关系由一个可能包含额外数据的中间表中介。在您的情况下,每个
用户
可以发送多个请求,也可以接收多个请求,
关系
是中介表,其中包含
状态
列作为附加数据

下面是代码的一个变体,它与您编写的代码保持相对接近:

from sqlalchemy.ext.associationproxy import association_proxy


class User(db.Model):
    __tablename__ = 'User'
    # The above is not necessary. If omitted, __tablename__ will be
    # automatically inferred to be 'user', which is fine.
    # (It is necessary if you have a __table_args__, though.)

    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(35), unique=False)
    # and so forth

    requested_rels = db.relationship(
        'Relationship',
        foreign_keys='Relationship.requesting_user_id',
        backref='requesting_user'
    )
    received_rels = db.relationship(
        'Relationship',
        foreign_keys='Relationship.receiving_user_id',
        backref='receiving_user'
    )
    aspiring_friends = association_proxy('received_rels', 'requesting_user')
    desired_friends = association_proxy('requested_rels', 'receiving_user')

    def __repr__(self):
        # and so forth


class Relationship(db.Model):
    # __tablename__ removed, becomes 'relationship'
    # __table_args__ removed, see below

    requesting_user_id = db.Column(db.Integer, db.ForeignKey('User.id'), primary_key=True)
    receiving_user_id = db.Column(db.Integer, db.ForeignKey('User.id'), primary_key=True)
    # Marking both columns above as primary_key creates a compound primary
    # key, which at the same time saves you the effort of defining the
    # UNIQUE constraint in __table_args__
    status = db.Column(db.Integer)

    # Implicit one-to-many relations: requesting_user, receiving_user.
    # Normally it would be more convenient to define those relations on
    # this side, but since you have two outgoing relationships with the
    # same table (User), you chose wisely to define them there.
(请注意,我是如何对行进行稍微不同的排序的,以及我是如何为外键列使用
\u id
后缀,同时为相应的
db.relationship
s保留相同的名称,而不使用后缀。我建议您也采用这种样式。)

现在,您有了一种直接从
User
模型访问传入和传出友谊请求以及相应用户的干净方法。但是,这仍然不够理想,因为您需要编写以下代码才能获得用户的所有确认好友:

def get_friends(user):
    requested_friends = (
        db.session.query(Relationship.receiving_user)
        .filter(Relationship.requesting_user == user)
        .filter(Relationship.status == CONFIRMED)
    )
    received_friends = (
        db.session.query(Relationship.requesting_user)
        .filter(Relationship.receiving_user == user)
        .filter(Relationship.status == CONFIRMED)
    )
    return requested_friends.union(received_friends).all()
(我没有对此进行测试;您可能还需要在这两个查询中与
User
进行
join
,以便
union
工作。)

更糟糕的是,模型名称
关系
以及模型中几个成员的名称似乎没有很好地表达它们的实际含义

您可以通过删除
Relationship.status
并将
Relationship
重命名为
FriendshipRequest
来改善问题。然后,将第二个
用户
-添加到名为
友谊
用户
关联模型,并向
用户
添加相应的第二组
db.Relationship
s和
关联代理
s。当有人发送友谊请求时,您将记录归档到
FriendshipRequest
。如果请求被接受,您将删除该记录并在
中用新记录替换它。这样,友谊的状态由存储一对用户的表编码,而不是使用状态代码。
友谊
模型可能如下所示:

class Friendship(db.Model):
    user1_id = db.Column(db.Integer, db.ForeignKey('User.id'), primary_key=True)
    user2_id = db.Column(db.Integer, db.ForeignKey('User.id'), primary_key=True)

    # Implicit one-to-many relations: user1, user2
    # (defined as backrefs in User.)
(将
User
中对应的
db.relationship
s和
association\u proxy
s留给读者作为练习。)


当您需要用户的确认好友时,这种方法可以为您节省一半的筛选操作。尽管如此,您仍然需要对两个查询进行
联合
,因为在
友谊
的每个实例中,您的用户可以是
user1
user2
。这本质上是困难的,因为我们处理的是自反对称关系。我认为有可能发明更优雅的方法来实现这一点,但我认为这将非常复杂,足以证明这里有一个关于堆栈溢出的新问题。

在本例中,您的
关系表是关联表。“朋友”关系的对称性与“友谊请求”关系的不对称性直接相反。我认为你应该把两者分开。