המחלקות PolyModel מאפשרות לאפליקציה להגדיר מודלים שתומכים בשאילתות פולימורפיות, בצורה גמישה יותר מהמחלקות הרגילות Model.
שאילתה שנוצרה ממחלקה נגזרת PolyModel יכולה להניב תוצאות שהן מופעים של המחלקה או של כל אחת ממחלקות המשנה שלה.
הוא מוגדר ב-google.appengine.ext.ndb.polymodel. בדוגמה הבאה אפשר לראות את הגמישות שמספקת המחלקה PolyModel.
from google.appengine.ext import ndb from google.appengine.ext.ndb import polymodel class Contact(polymodel.PolyModel): phone_number = ndb.PhoneNumberProperty() address = ndb.PostalAddressProperty() class Person(Contact): first_name = ndb.StringProperty() last_name = ndb.StringProperty() mobile_number = ndb.PhoneNumberProperty() class Company(Contact): name = ndb.StringProperty() fax_number = ndb.PhoneNumberProperty() p = Person(phone_number='1-206-555-9234', address='123 First Ave., Seattle, WA, 98101', first_name='Alfred', last_name='Smith', mobile_number='1-206-555-0117') p.put() c = Company(phone_number='1-503-555-9123', address='P.O. Box 98765, Salem, OR, 97301', name='Data Solutions, LLC', fax_number='1-503-555-6622') c.put() for contact in Contact.query(): print 'Phone: %s\nAddress: %s\n\n' % (contact.phone_number, contact.address)
הפונקציה Contact.query() מחזירה מופעים של Person ו-Company. אם Contact נגזר מ-Model במקום מ-PolyModel, לכל מחלקה יהיה ערך שונה של kind והפונקציה Contact.query() לא תחזיר מופעים של מחלקות משנה מתאימות של Contact.
כדי לאחזר רק מופעים של Person, צריך להשתמש ב-Person.query(). אפשר גם להשתמש ב-Contact.query(Contact.class_ == 'Person').
בנוסף לשיטות הרגילות של Model, ל-PolyModel יש כמה שיטות מעניינות של מחלקה:
-
_get_kind(): השם של מחלקת הבסיס, למשלPerson._get_kind() == 'Contact'. יכול להיות שהמחלקה הבסיסית, Contact בדוגמה הזו, תבטל את השיטה הזו כדי להשתמש בשם אחר כסוג שמשמש במאגר הנתונים (לכל ההיררכיה שמתחילה כאן). -
_class_name(): השם של המחלקה הנוכחית, למשלPerson._class_name() == 'Person'. מחלקת עלים, Person בדוגמה שלנו, יכולה לבטל את השיטה הזו כדי להשתמש בשם אחר כשם המחלקה ובמפתח המחלקה. גם מחלקה שהיא לא עלה יכולה לבטל את השיטה הזו, אבל צריך לשים לב: מחלקות המשנה שלה צריכות גם לבטל אותה, אחרת כולן ישתמשו באותו שם מחלקה, ואתם תתבלבלו מאוד. -
_class_key(): רשימה של שמות מחלקות שמציגה את ההיררכיה. לדוגמה:Person._class_key() == ['Contact', 'Person']. בהיררכיות עמוקות יותר, הפונקציה הזו תכלול את כל הבסיסים ביןPolyModelלבין המחלקה הנוכחית, כולל המחלקה הנוכחית, אבל לא כולל את PolyModel עצמו. הערך הזה זהה לערך של המאפייןclass_. השם של מאגר הנתונים הוא 'class'.
מכיוון ששם המחלקה משמש במאפיין class_, והמאפיין הזה משמש להבחנה בין מחלקות המשנה, שמות המחלקות (כפי שמוחזרים על ידי _class_name()) צריכים להיות ייחודיים בין מחלקות המשנה האלה.