מחלקת Model שממנה מתבצעת ירושה מייצגת את מבנה הישויות שמאוחסנות במאגר הנתונים.
האפליקציות מגדירות מחלקות של מודלים כדי לציין את המבנה של הישויות שלהן, ואז יוצרות מופעים של המחלקות האלה כדי ליצור ישויות.
כל מחלקות המודלים חייבות להיות נגזרות (ישירות או עקיפות) מהמחלקה 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 של מודל האב או
Noneשל מודל ברמה העליונה. אם משתמשים בדגל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
ל-constructor, ומגדירים את המפתח לאחר מכן.
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)
- Returns an entity by ID. זה בעצם קיצור של
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 that runs after
put()
אינטרוספקציה
אפשר להשתמש בשיטות האלה כדי לבדוק את המאפיינים וההגדרות של מודל נתון. האפשרות הזו שימושית אם אתם כותבים ספרייה או פונקציה שמקבלות כמה סוגים של מודלים.
חיפוש לפי סוג
לכל מודל יש סוג, שבדרך כלל זהה לשם הסיווג, אלא אם הוגדר אחרת. אפשר להשתמש ב-kind כדי למצוא את מחלקת המודל המשויכת באמצעות
_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.
אם אתם יוצרים ספריות של צד שלישי שמתקשרות עם מודלים שרירותיים, מומלץ להשתמש בשיטות עם הקידומת _.