Membuat Model Entity

Anda perlu membuat class model untuk entity Anda. Anda dapat melakukannya dengan dua cara:

  • Buat class model yang menentukan properti entity.
  • Buat class model expando yang tidak menentukan entity terlebih dahulu.

Dokumen ini menjelaskan cara membuat setiap jenis class model ini. Panduan ini juga menjelaskan cara membuat hook model, sehingga aplikasi Anda dapat menjalankan beberapa kode sebelum atau setelah beberapa jenis operasi, misalnya, sebelum setiap get().

Membuat class model dengan properti

Sebelum membuat entity, Anda harus membuat class model yang menentukan satu atau beberapa properti entity. Contoh:

from google.appengine.ext import ndb
...
class Account(ndb.Model):
    username = ndb.StringProperty()
    userid = ndb.IntegerProperty()
    email = ndb.StringProperty()

tempat di mana Anda ingin setiap entity Akun memiliki properti untuk nama pengguna, ID pengguna, dan email.

Untuk mengetahui daftar lengkap jenis properti, lihat Referensi Properti Entitas.

Membuat class model expando

Anda tidak perlu menggunakan class model yang mendefinisikan properti terlebih dahulu. Subclass model khusus yang disebut Expando mengubah perilaku entitynya sehingga setiap atribut yang ditetapkan akan disimpan ke penyimpanan data. Perlu diperhatikan bahwa atribut tersebut tidak boleh diawali dengan garis bawah.

Berikut cara membuat model expando:

class Mine(ndb.Expando):
    pass
...
e = Mine()
e.foo = 1
e.bar = 'blah'
e.tags = ['exp', 'and', 'oh']
e.put()

Kode ini menulis entity ke penyimpanan data dengan foo properti dengan nilai bilangan bulat1 , bar properti dengan nilai string'blah' , dan pesan berulangtag properti dengan nilai string'exp' dan'and' , dan'oh'. Properti diindeks, dan Anda dapat memeriksanya menggunakan atribut _properties entity:

return e._properties
# {
#     'foo': GenericProperty('foo'),
#     'bar': GenericProperty('bar'),
#     'tags': GenericProperty('tags', repeated=True)
# }

Expando yang dibuat dengan mendapatkan nilai dari penyimpanan data memiliki properti untuk semua nilai properti yang disimpan di penyimpanan data.

Aplikasi dapat menambahkan properti yang telah ditetapkan ke subclass Expando:

class FlexEmployee(ndb.Expando):
    name = ndb.StringProperty()
    age = ndb.IntegerProperty()
...
employee = FlexEmployee(name='Sandy', location='SF')

Ini memberi employee atribut name dengan nilai 'Sandy', atribut age dengan nilai None, dan atribut dinamis location dengan nilai 'SF'.

Untuk membuat subclass Expando yang propertinya tidak diindeks, tetapkan _default_indexed = False dalam definisi subclass:

class Specialized(ndb.Expando):
    _default_indexed = False
...
e = Specialized(foo='a', bar=['b'])
return e._properties
# {
#     'foo': GenericProperty('foo', indexed=False),
#     'bar': GenericProperty('bar', indexed=False, repeated=True)
# }

Anda juga dapat menetapkan _default_indexed pada entity Expando. Dalam hal ini, perubahan ini akan memengaruhi semua properti yang dipilih setelah ditetapkan.

Teknik berguna lainnya adalah membuat kueri jenis Expando untuk properti dinamis. Kueri seperti berikut

FlexEmployee.query(FlexEmployee.location == 'SF')

tidak akan berfungsi karena class tidak memiliki objek properti untuk properti lokasi. Sebagai gantinya, gunakan GenericProperty, yang digunakan Expando class untuk properti dinamis:

FlexEmployee.query(ndb.GenericProperty('location') == 'SF')

Menggunakan Hook Model

NDB menawarkan mekanisme hooking yang ringan. Dengan menentukan hook, aplikasi dapat menjalankan beberapa kode sebelum atau setelah beberapa jenis operasi; misalnya, Model mungkin menjalankan beberapa fungsi sebelum setiap get().

Fungsi hook berjalan saat menggunakan metode yang sesuai versi sinkron, asinkron, dan multi-versi. Misalnya, hook "pre-get" akan berlaku untuk semua get(), get_async(), dan get_multi(). Ada versi pre-RPC dan post-RPC dari setiap hook.

Hook dapat berguna untuk hal-hal berikut:

  • cache kueri
  • mengaudit aktivitas Cloud Datastore per pengguna
  • meniru pemicu database

Contoh berikut menunjukkan cara menentukan fungsi hook:

from google.appengine.ext import ndb
...
class Friend(ndb.Model):
    name = ndb.StringProperty()

    def _pre_put_hook(self):
        _notify('Gee wiz I have a new friend!')

    @classmethod
    def _post_delete_hook(cls, key, future):
        _notify('I have found occasion to rethink our friendship.')
...
f = Friend()
f.name = 'Carole King'
f.put()  # _pre_put_hook is called
fut = f.key.delete_async()  # _post_delete_hook not yet called
fut.get_result()  # _post_delete_hook is called

Jika Anda menggunakan post-hook dengan API asinkron, hook akan dipicu dengan memanggil check_result(), get_result(), atau menghasilkan (di dalam tasklet) masa depan metode asinkron. Post-hook tidak memeriksa apakah RPC berhasil; hook tetap berjalan terlepas dari kegagalan.

Semua post-hook memiliki argumen Future di akhir signature panggilan. Objek Future ini menyimpan hasil tindakan. Anda dapat memanggil get_result() pada Future ini untuk mendapatkan hasilnya; Anda dapat memastikan bahwa get_result() tidak akan melakukan pemblokiran, karena Future sudah selesai pada saat hook dipanggil.

Mengajukan pengecualian selama pre-hook akan mencegah permintaan terjadi. Meskipun hook dipicu di dalam metode <var>*</var>_async, Anda tidak dapat mempersiapkan RPC terlebih dahulu dengan memunculkan tasklets.Return di hook pre-RPC.

Langkah selanjutnya