מחלקת Model שממנה מתבצעת ירושה מייצגת את מבנה הישויות שמאוחסנות ב-Datastore.
אפליקציות מגדירות מחלקות של מודלים כדי לציין את המבנה של הישויות שלהן, ואז יוצרות מופעים של המחלקות האלה כדי ליצור ישויות.
כל מחלקות המודלים חייבות להיות נגזרות (ישירות או עקיפות) מהמחלקה Model.
בדף הזה מופיע תיעוד של הפניות ל-API. לסקירה כללית, אפשר לעיין במאמר NDB Entities and Keys.
מבוא
מחלקת Model
שממנה מתבצעת ירושה מתארת ישויות של Datastore.
כל מחלקות המודלים צריכות לרשת (ישירות או בעקיפין) מ-Model. אפשר להשתמש בהקצאות פשוטות בהגדרת מחלקת המודל כדי להצהיר על המבנה של המודל:
from google.appengine.ext import ndb class Person(ndb.Model): name = ndb.StringProperty() age = ndb.IntegerProperty()
עכשיו אפשר ליצור ישות מסוג Person ולכתוב אותה ב-Datastore:
p = Person(name='Arthur Dent', age=42) k = p.put()
הערך המוחזר מהפונקציה put() הוא Key, שאפשר להשתמש בו כדי לאחזר את אותה ישות מאוחר יותר:
p2 = k.get() p2 == p # Returns True
כדי לעדכן ישות, פשוט משנים את המאפיינים שלה ומחזירים אותה לכתיבה (שימו לב שהפעולה הזו לא משנה את המפתח):
p2.name = 'Arthur Philip Dent' p2.put()
אפשר גם למחוק ישות (באמצעות המפתח):
k.delete()
הגדרות המאפיינים בגוף המחלקה מציינות למערכת את השמות ואת הסוגים של השדות שייאוחסנו ב-Datastore, אם צריך ליצור להם אינדקס, מה ערך ברירת המחדל שלהם ועוד. יש הרבה סוגים שונים של נכסים.
הערך של kind בדרך כלל שווה לשם המחלקה (לא כולל את שם המודול או כל היקף אב אחר). כדי לבטל את הסוג (שימושי לשינויים בסכימה), מגדירים שיטת מחלקה בשם _get_kind(), באופן הבא:
class MyModel(ndb.Model): @classmethod def _get_kind(cls): return 'AnotherKind'
באפליקציה אסור להגדיר שני סוגים של מודלים עם אותו סוג, גם אם הם נמצאים במודולים שונים. הסוגים של אפליקציה נחשבים ל"מרחב שמות" גלובלי.
Model
מחלקות משנה יכולות להגדיר hooks לפני ואחרי שיחות
לרוב הפעולות (get, put, delete, allocate_ids).
Constructor
בדרך כלל אפליקציה לא קוראת ל-Model(), אבל סביר להניח שהיא קוראת לבונה של מחלקה שיורשת מ-Model.
הפעולה הזו יוצרת מופע חדש של המודל הזה, שנקרא גם ישות.
הישות שנוצרה לא נכתבת אוטומטית ב-Datastore.
כדי שזה יקרה, צריך לכתוב אותה ב-Datastore באמצעות קריאה מפורשת
ל-put().
ארגומנטים:
Model תומך בארגומנטים הבאים של מילות מפתח:
- key מופע
- Key של המודל הזה. אם משתמשים בפרמטר
key, הפרמטריםidו-parentחייבים להיותNone(ברירת המחדל). - id
- מזהה המפתח של המודל הזה. אם משתמשים ב-
id, המפתח חייב להיותNone(ברירת המחדל). - parent
- Key instance for the parent model or
Nonefor a top-level one. אם משתמשים בדגלparent, הערך של הדגלkeyחייב להיותNone. - namespace
- Namespace לשימוש עבור הישות הזו, או
None(ברירת מחדל) לשימוש במרחב השמות הנוכחי. אם משתמשים בדגלnamespace, הערך של הדגלkeyחייב להיותNone.
אפליקציה יכולה גם להשתמש במיפוי של ארגומנטים של מילות מפתח למאפיינים של המודל. לדוגמה, הקוד הבא פועל:
class Person(ndb.Model): name = StringProperty() age = IntegerProperty() p = Person(name='Arthur Dent', age=42)
אי אפשר להגדיר בקלות מאפיין בשם key, id, parent או namespace.
אם מעבירים, לדוגמה, את הערך key="foo" בקונסטרוקטור או בקריאה populate(), הערך הזה מוגדר כמפתח של הישות, ולא כמאפיין של נכס בשם key.
הערה:
אם מחליפים את הקונסטרוקטור במחלקת משנה של Model, צריך לשים לב לכך שהקונסטרוקטור נקרא גם באופן מרומז במקרים מסוימים, ולוודא שהקריאות האלה נתמכות. כשקוראים ישות מ-Datastore, קודם נוצרת ישות ריקה על ידי קריאה לקונסטרוקטור ללא ארגומנטים, ואחרי כן המפתח וערכי המאפיינים מוגדרים אחד אחרי השני. כשמשתמשים ב-get_or_insert() או ב-get_or_insert_async() כדי ליצור מופע חדש, הארגומנטים **constructor_args מועברים לקונסטרוקטור, והמפתח מוגדר לאחר מכן.
Class Methods
- allocate_ids(size=None, max=None, parent=None, **ctx_options)
-
מקצה טווח של מזהי מפתחות למחלקת המודל הזו.
ארגומנטים
- size
- מספר המזהים להקצאה. אפשר לציין את
sizeאו אתmax, אבל לא את שניהם. - max
- המזהה המקסימלי להקצאה. אפשר לציין את
sizeאו אתmax, אבל לא את שניהם. - parent
- מפתח האב שעבורו יוקצו המזהים.
- **ctx_options
- אפשרויות הקשר
מחזירה טאפל עם (התחלה, סיום) לטווח שהוקצה, כולל.
אפליקציה לא יכולה לקרוא ל-
allocate_ids()בעסקה. - allocate_ids_async(size=None, max=None, parent=None, **ctx_options)
-
גרסה אסינכרונית של allocate_ids.
הפונקציה מחזירה אובייקט
Futureשהתוצאה שלו היא טופל עם (התחלה, סיום) לטווח שהוקצה, כולל. - get_by_id(id, parent=None, app=None, namespace=None, **ctx_options)
- מחזירה ישות לפי מזהה. זוהי למעשה קיצור דרך ל-
Key(cls, id).get().ארגומנטים
- id
- מזהה מפתח מסוג מחרוזת או מספר שלם.
- parent
- המפתח של המודל שאותו רוצים לקבל.
- app (ארגומנט של מילת מפתח)
- מזהה האפליקציה. אם לא מצוין, הנתונים מתקבלים עבור האפליקציה הנוכחית.
- namespace (ארגומנט של מילת מפתח)
- מרחב שמות. אם לא מציינים מרחב שמות, המערכת מקבלת נתונים עבור מרחב השמות שמוגדר כברירת מחדל.
- **ctx_options
- אפשרויות הקשר
הפונקציה מחזירה מופע של מודל או
Noneאם המודל לא נמצא. - get_by_id_async(id, parent=None, app=None, namespace=None, **ctx_options)
- גרסה אסינכרונית של get_by_id.
הפונקציה מחזירה אובייקט
Futureשהתוצאה שלו היא מופע של מודל אוNoneאם לא נמצא מופע. - get_or_insert(key_name, parent=None, app=None, namespace=None, context_options=None, **constructor_args)
- שליפה טרנזקציונלית של ישות קיימת או יצירה של ישות חדשה.
ארגומנטים
- key_name
- שם המפתח (כלומר, מזהה מפתח מסוג מחרוזת) לאחזור או ליצירה.
- parent
- המפתח של ישות האם, אם יש.
- אפליקציה
- מזהה האפליקציה. אם לא מצוין, הנתונים מתקבלים עבור האפליקציה הנוכחית.
- namespace
- מרחב שמות. אם לא מציינים מרחב שמות, המערכת מקבלת נתונים עבור מרחב השמות שמוגדר כברירת מחדל.
- context_options
- אפשרויות הקשר
הפונקציה הזו מקבלת גם ארגומנטים של מילות מפתח להעברה לבונה של מחלקת המודל, אם מופע של שם המפתח שצוין עדיין לא קיים. אם מופע עם
key_nameוהורה שסופקו כבר קיים, הארגומנטים האלה יימחקו.מחזירה מופע קיים של מחלקת
Modelעם שם המפתח וההורה שצוינו, או מופע חדש שנוצר זה עתה.הפונקציה הזו משתמשת בעסקה. אם הקוד שמפעיל את הפונקציה הזו כבר נמצא בטרנזקציה, הפונקציה הזו מנסה לעשות שימוש חוזר בטרנזקציה הקיימת. אם קבוצת הישויות של הפונקציה הזו לא תואמת לעסקה הקיימת, יכולה להתרחש שגיאה.
- get_or_insert_async(key_name, parent=None, app=None, namespace=None, context_options=None, **constructor_args)
-
זוהי הגרסה האסינכרונית של get_or_insert.
הפונקציה מחזירה אובייקט
Futureשהתוצאה שלו היא מופע קיים של מחלקתModelעם שם המפתח וההורה שצוינו, או מופע חדש שנוצר זה עתה. - query([filter1, filter2, ...,] ancestor=None, app=None, namespace=None, filters=None, orders=None, default_options=None, projection=None distinct=False group_by=None)
-
יוצרת אובייקט
Queryלכיתה הזו, כמו שמתואר במאמר שאילתות.הארגומנט של מילת המפתח
distinctהוא קיצור של group_by = projection. כל הארגומנטים האחרים של מילות המפתח מועברים אל הבונה של Query.אם מציינים ארגומנטים מיקומיים, הם משמשים להגדרת מסננים ראשוניים.
מחזירה אובייקט
Query.
Instance Methods
- populate(**constructor_options)
-
מגדיר את הערכים של מאפייני הישות. ארגומנטי מילות המפתח שלו מזהים באופן אוטומטי שמות של מאפיינים, כמו בבונה.
- put(**ctx_options)
-
כתיבת נתוני הישות אל Datastore. מחזירה את המפתח של הישות.
ארגומנטים
- **ctx_options
- אפשרויות הקשר
- put_async(**ctx_options)
-
כתיבת הנתונים של הישות אל Datastore באופן אסינכרוני. הפונקציה מחזירה אובייקט
Future. התוצאה של האובייקטFutureתהיה Key של הישות.ארגומנטים
- **ctx_options
- אפשרויות הקשר
- to_dict(include=all, exclude=None)
-
הפונקציה מחזירה
dictשמכיל את ערכי המאפיינים של המודל. ערכי הנכסים שלStructuredPropertyושלLocalStructuredPropertyמומרים באופן רקורסיבי למילונים.ארגומנטים:
- include
- רשימה אופציונלית של מאפיינים שרוצים לכלול. ברירת מחדל: כל המשתמשים.
- exclude
- רשימה אופציונלית של נכסים להחרגה. אם יש חפיפה בין include לבין exclude, אז exclude "מנצח".
הערה: אם ערך של מאפיין הוא אובייקט שניתן לשינוי (למשל רשימה שמייצגת מאפיין חוזר, או מילון או רשימה שמאוחסנים ב-
JsonProperty), אלא אם הערך מומר באופן מפורש (למשל במקרה שלStructuredProperty), אותו אובייקט מוחזר במילון שמאוחסן בישות. במקרים כאלה, שינוי המילון ישנה את הישות, ולהפך.
נתוני מופע
- key
- מאפיין מיוחד לאחסון מפתח המודל.
Hook Methods
מחלקת משנה של Model באפליקציה יכולה להגדיר אחת או יותר מהשיטות האלה כשיטות 'hook' לפני או אחרי פעולה.
לדוגמה, כדי להריץ קוד מסוים לפני כל פעולת get, מגדירים את השיטה _pre_get_hook() של מחלקת המשנה של המודל. המלצות לכתיבת פונקציות hook מופיעות במאמר Model Hooks.
- @classmethod
_pre_allocate_ids_hook(cls, size, max, parent) - Hook שמופעל לפני
allocate_ids() - @classmethod
_post_allocate_ids_hook(cls, size, max, parent, future) - Hook שמופעל אחרי
allocate_ids() - @classmethod
_pre_delete_hook(cls, key) - Hook שמופעל לפני
delete() - @classmethod
_post_delete_hook(cls, key, future) - Hook שמופעל אחרי
delete() - @classmethod
_pre_get_hook(cls, key) - Hook שמופעל לפני
Key.get()כשמקבלים ישות של המודל הזה. - @classmethod
_post_get_hook(cls, key, future) - Hook שמופעל אחרי
Key.get()כשמקבלים ישות של המודל הזה. - _pre_put_hook(self)
- Hook שמופעל לפני
put() - _post_put_hook(self, future)
- Hook שמופעל אחרי
put()
אינטרוספקציה
אתם יכולים להשתמש בשיטות האלה כדי לבדוק את המאפיינים וההגדרות של מודל מסוים. זה שימושי אם אתם כותבים ספרייה או פונקציה שמקבלת כמה סוגים של מודלים.
חיפוש לפי סוג
לכל מודל יש סוג, שבדרך כלל זהה לשם הסיווג, אלא אם הוגדר אחרת. אפשר להשתמש בסוג כדי למצוא את סיווג המודל המשויך באמצעות _lookup_model.
class Animal(ndb.Model): type = ndb.StringProperty() print Animal._get_kind() # 'Animal' print ndb.Model._lookup_model('Animal') # class Animal
הערה: _lookup_model פועל רק עבור מחלקות מודלים שכבר יובאו על ידי האפליקציה.
מאפיינים
אפשר להשתמש בפקודה _properties כדי לקבל רשימה של כל המאפיינים שמשויכים למודל.
class User(ndb.Model): name = ndb.StringProperty() email = ndb.StringProperty() print User._properties # {'email': StringProperty('email'), 'name': StringProperty('name')}
_properties פועל גם במופעים של Expando.
class Example(ndb.Expando): pass e = Example() e.foo = 1 e.bar = 'blah' e.tags = ['exp', 'and', 'oh'] print e._properties # {'foo': GenericProperty('foo'), 'bar': GenericProperty('bar'), # 'tags': GenericProperty('tags', repeated=True)}
אפשר לבצע בדיקה של מופעי נכסים. האפשרויות שמועברות ל-constructor זמינות כמאפיינים עם הקידומת _.
print User._properties['email']._name # 'email' print User._properties['email']._required # False print User._properties['email']._default # None print User._properties['email']._choices # None print User._properties['email']._compressed # False print User._properties['email']._indexed # True print User._properties['email']._compressed # False print User._properties['email']._repeated # False print User._properties['email']._verbose_name # None print isinstance(User._properties['email'], ndb.StringProperty) # True
כינויים של שיטות
לכל שיטה במחלקה Model יש כינוי עם הקידומת _. לדוגמה,
_put() שווה ל-put(). המשמעות היא שאפשר להשתמש במאפיינים עם שמות שמתנגשים עם שמות של שיטות, בתנאי שתמיד משתמשים בשיטות עם הקידומת _. עם זאת, שימו לב שאי אפשר לציין בבנאי מאפיינים בשמות key, parent או id.
class MyModel(ndb.Model): put = ndb.StringProperty() query = ndb.StringProperty() key = ndb.StringProperty() entity = MyModel() entity.put = '1' entity.query = '2' entity.key = '3' entity._put() print entity # MyModel(key=Key('MyModel', ...), put=u'1', query=u'2', key=u'3') print MyModel._query().fetch() # same as above.
אם אתם יוצרים ספריות של צד שלישי שפועלות עם מודלים שרירותיים,
מומלץ להשתמש בשיטות עם הקידומת _.