अन्य बातों के अलावा, आप एसोसिएशन प्रॉक्सी . एक एसोसिएशन प्रॉक्सी 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
. के हर उदाहरण में . यह स्वाभाविक रूप से कठिन है क्योंकि हम एक प्रतिवर्त सममित संबंध के साथ काम कर रहे हैं। मुझे लगता है कि इसे करने के लिए और भी शानदार तरीकों का आविष्कार करना संभव है, लेकिन मुझे लगता है कि स्टैक ओवरफ्लो पर यहां एक नए प्रश्न की गारंटी देने के लिए यह काफी जटिल होगा।