複数のオブジェクトを返すクエリからManyToManyオブジェクトを簡単にフェッチする方法はありますか?私が今やっているやり方は、私が好きなほどセクシーな気がしません。ここで私は私の見解で、今それをやっている方法です:ManyToManyオブジェクトを複数のオブジェクトから中間テーブル経由で取得する
contacts = Contact.objects.all()
# Use Custom Manager Method to Fetch Each Contacts Phone Numbers
contacts = PhoneNumber.objects.inject(contacts)
マイモデル:
class PhoneNumber(models.Model):
number = models.CharField()
type = models.CharField()
# My Custom Manager
objects = PhoneNumberManager()
class Contact(models.Model):
name = models.CharField()
numbers = models.ManyToManyField(PhoneNumber, through='ContactPhoneNumbers')
class ContactPhoneNumbers(models.Model):
number = models.ForeignKey(PhoneNumber)
contact = models.ForeignKey(Contact)
ext = models.CharField()
マイカスタムマネージャー:
class PhoneNumberManager(models.Manager):
def inject(self, contacts):
contact_ids = ','.join([str(item.id) for item in contacts])
cursor = connection.cursor()
cursor.execute("""
SELECT l.contact_id, l.ext, p.number, p.type
FROM svcontact_contactphonenumbers l, svcontact_phonenumber p
WHERE p.id = l.number_id AND l.contact_id IN(%s)
""" % contact_ids)
result = {}
for row in cursor.fetchall():
id = str(row[0])
if not id in result:
result[id] = []
result[id].append({
'ext': row[1],
'number': row[2],
'type': row[3]
})
for contact in contacts:
id = str(contact.id)
if id in result:
contact.phonenumbers = result[id]
return contacts
うん、これは間違っている可能性があります。 cons = Contact.objects.all()[0:50]そしてnum = ContactPhoneNumbers.objects.filter(contact__in = cons)は、150以上のデータベースクエリを実行します。 – Matt
あああ! contact_phone_numbers = ContactPhoneNumbers。 objects.select_related().filter(contact__in = contacts) 非常にセクシーです。 – Matt
私はそれが連絡先をもう一度引っ張らないほどスマートであるかどうか疑問に思います。ちょっと質問を調べなければなりません。 – Matt