sql >> データベース >  >> RDS >> PostgreSQL

sqlalchemyは多対1の友情に対称的です

    特に、アソシエーションプロキシ> 。アソシエーションプロキシは、追加のデータを含む可能性のある中間テーブルによって仲介される多対多の関係があることをSQLAlchemyに通知します。あなたの場合、各User 複数のリクエストを送信でき、複数のリクエストとRelationshipを受信することもできます statusを含む仲介テーブルです 追加データとしての列。

    これは、あなたが書いたものに比較的近いままであるあなたのコードの変形です:

    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.
    

    (行の順序が少し異なる方法と、_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()
    

    (私はこれをテストしませんでした。joinも必要になる場合があります Userを使用 unionの順序で両方のクエリで 動作します。)

    さらに悪いことに、モデル名Relationship また、モデル内のいくつかのメンバーの名前は、実際の意味をうまく伝えていないようです。

    Relationship.statusを削除すると、問題を改善できます。 Relationshipの名前を変更します FriendshipRequestへ 。次に、2番目のUserを追加します -to-User Friendshipと呼ばれる関連付けモデル 対応する2番目のdb.Relationshipのセットを追加します s with backref sおよびassociation_proxy sからUser 。誰かが友情リクエストを送信したら、FriendshipRequestにレコードを提出します 。リクエストが受け入れられた場合は、レコードを削除して、Friendshipの新しいレコードに置き換えます。 。このように、ステータスコードを使用する代わりに、友情のステータスは、ユーザーのペアを格納するテーブルによってエンコードされます。 Friendship モデルは次のようになります:

    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.)
    

    (対応するdb.relationship sおよびassociation_proxy s User 読者への演習として残されています。)

    このアプローチにより、ユーザーの確認済みの友達が必要な場合に、フィルタリング操作の半分を節約できます。それでも、unionを作成する必要があります ユーザーはuser1のいずれかである可能性があるため、2つのクエリのうち またはuser2 Friendshipの各インスタンスで 。私たちは反射対称関係を扱っているので、これは本質的に困難です。それを行うためのさらにエレガントな方法を発明することは可能だと思いますが、それはここStackOverflowで新しい質問を正当化するのに十分複雑になると思います。




    1. innondbエンジンを使用したmysqlデータベースへのPythonスクリプトからの挿入の問題

    2. Initcapは4文字未満の単語をスキップします

    3. Jasper Report:クラス'org.postgresql.util.PGmoney'のフィールド'x'の値を取得できません

    4. チェックボックス、php、mysqlを使用してデータベーステーブルを更新します