PostgreSQL
 sql >> डेटाबेस >  >> RDS >> PostgreSQL

sqlalchemy सममित कई से एक दोस्ती

अन्य बातों के अलावा, आप एसोसिएशन प्रॉक्सी . एक एसोसिएशन प्रॉक्सी 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 के लिए प्रत्यय के बिना एक ही नाम आरक्षित करते समय विदेशी कुंजी स्तंभों के लिए प्रत्यय एस। मेरा सुझाव है कि आप भी इस शैली को अपनाएं।)

अब आपके पास सीधे अपने 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 . फिर, एक दूसरा User जोड़ें -to-User एसोसिएशन मॉडल जिसे Friendship कहा जाता है और db.Relationship . का संगत दूसरा सेट जोड़ें 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 एस और association_proxy User में s पाठक के लिए एक अभ्यास के रूप में छोड़ दिया जाता है।)

जब आपको किसी उपयोगकर्ता के पुष्टि किए गए मित्रों की आवश्यकता होती है तो यह दृष्टिकोण आपको फ़िल्टरिंग संचालन के आधे हिस्से को बचाता है। फिर भी, आपको एक union बनाना होगा दो प्रश्नों में से क्योंकि आपका उपयोगकर्ता या तो user1 . हो सकता है या user2 Friendship . के हर उदाहरण में . यह स्वाभाविक रूप से कठिन है क्योंकि हम एक प्रतिवर्त सममित संबंध के साथ काम कर रहे हैं। मुझे लगता है कि इसे करने के लिए और भी शानदार तरीकों का आविष्कार करना संभव है, लेकिन मुझे लगता है कि स्टैक ओवरफ्लो पर यहां एक नए प्रश्न की गारंटी देने के लिए यह काफी जटिल होगा।




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Postgresql में सभी डेटाबेस और उनके स्कीमा को कैसे सूचीबद्ध करें?

  2. क्या कोई मल्टीबाइट-जागरूक Postgresql Levenshtein है?

  3. SQLite3 LIKE या PostgreSQL ILIKE के लिए सामान्य रूबी समाधान?

  4. रूबी 'पीजी' मणि libpq.5.dylib (OSX पर) की गलत प्रति से जुड़ती है

  5. pgAudit का उपयोग करके PostgreSQL का ऑडिट करना