Aucun changement requis au niveau de Datastore
Au cas où vous vous poseriez la question, sachez que même si les API sont différentes, NDB et l'ancien package ext.db écrivent exactement les mêmes données dans Datastore. Cela signifie que vous n'avez aucune conversion à faire dans votre datastore et que vous pouvez panacher à volonté les API NDB et ext.db dans votre code, à condition que le schéma que vous utilisez soit équivalent. Vous pouvez même effectuer des conversions entre clés ext.db et NDB au moyen des méthodes ndb.Key.from_old_key() et key.to_old_key().
Différences générales
NDB est pointilleux au sujet des types. Par exemple, avec db, lorsqu'une clé est requise, vous pouvez transmettre aussi bien une entité qu'une chaîne. Avec NDB, vous devez impérativement transmettre une clé.
NDB est pointilleux au sujet des listes. Par exemple, dans db,
db.put()
accepte une entité ou une liste d'entités. Dans NDB, utilisezentity.put()
pour une seule entité, maisndb.put_multi(<list>)
pour une liste d'entités.NDB préfère les méthodes aux fonctions. Par exemple, au lieu de
db.get(key)
etdb.put(entity)
, NDB utilisekey.get()
etentity.put()
.NDB évite de proposer deux API réalisant la même action. (Toutefois, il peut proposer deux API effectuant des opérations légèrement différentes.)
Comparatif des appels API
Les tableaux ci-dessous illustrent les similitudes et les différences entre ndb et l'ancien module ext.db. Consultez la documentation officielle de NDB pour une introduction et une documentation de référence complète sur NDB.
Classe de modèle
google.appengine.ext.db | ndb.model |
class MyModel(db.Model): foo = db.StringProperty() |
class MyModel(ndb.Model): foo = ndb.StringProperty() |
@classmethod def kind(cls): return 'Foo' |
@classmethod def _get_kind(cls): return 'Foo' |
MyModel.kind() |
MyModel._get_kind() |
MyModel.properties() model_instance.properties() |
MyModel._properties # No () !! model_entity._properties |
MyExpando.dynamic_properties() |
MyExpando._properties # No () !! |
Entités
google.appengine.ext.db | ndb.model |
MyModel(key_name='my_key') |
MyModel(id='my_key') |
MyModel(key_name='my_key', parent=model_instance) |
MyModel(id='my_key', parent=model_instance.key) |
key = model_instance.key() |
key = model_instance.key # No () !! |
model_instance = MyModel( foo='foo', bar='bar', baz='baz') |
model_instance = MyModel( foo='foo', bar='bar', baz='baz') |
model_instance.foo = 'foo' model_instance.bar = 'bar' model_instance.baz = 'baz' |
model_instance.foo = 'foo' model_instance.bar = 'bar' model_instance.baz = 'baz' # or a shortcut... model_instance.populate( foo='foo', bar='bar', baz='baz') |
model_instance.is_saved() |
Pas d'équivalent direct. Pour une solution possible, reportez-vous à Stack Overflow. |
Get
google.appengine.ext.db | ndb.model |
MyModel.get_by_key_name('my_key') |
MyModel.get_by_id('my_key') |
MyModel.get_by_id(42) |
MyModel.get_by_id(42) |
db.get(key) |
key.get() |
MyModel.get(key) |
key.get() |
db.get(model_instance) |
model_instance.key.get() |
db.get(list_of_keys) |
ndb.get_multi(list_of_keys) |
db.get(list_of_instances) |
ndb.get_multi([x.key for x in list_of_instances]) |
MyModel.get_or_insert('my_key', parent=model_instance, foo='bar') |
MyModel.get_or_insert('my_key', parent=model_instance.key, foo='bar') |
Écrire
google.appengine.ext.db | ndb.model |
db.put(model_instance) |
model_instance.put() |
db.put(list_of_model_instances) |
ndb.put_multi( list_of_model_instances) |
Supprimer
google.appengine.ext.db | ndb.model |
model_instance.delete() |
model_instance.key.delete() |
db.delete(model_instance) |
model_instance.key.delete() |
db.delete(key) |
key.delete() |
db.delete(list_of_model_instances) |
ndb.delete_multi([m.key for m in list_of_model_instances]) |
db.delete(list_of_keys) |
ndb.delete_multi(list_of_keys) |
Propriétés
google.appengine.ext.db | ndb.model |
db.BlobProperty() |
ndb.BlobProperty() |
db.BooleanProperty() |
ndb.BooleanProperty() |
db.ByteStringProperty() |
ndb.BlobProperty(indexed=True) |
db.CategoryProperty() |
ndb.StringProperty() |
db.DateProperty() |
ndb.DateProperty() |
db.DateTimeProperty() |
ndb.DateTimeProperty() |
db.EmailProperty() |
ndb.StringProperty() |
db.FloatProperty() |
ndb.FloatProperty() |
db.GeoPtProperty() |
ndb.GeoPtProperty() |
db.IMProperty() |
Aucun équivalent. |
db.IntegerProperty() |
ndb.IntegerProperty() |
db.LinkProperty() |
ndb.StringProperty() Possède une taille maximale de 500. Pour des URL plus longues, utilisez |
db.ListProperty(bool) db.ListProperty(float) db.ListProperty(int) db.ListProperty(db.Key) # etc. |
ndb.BooleanProperty(repeated=True) ndb.FloatProperty(repeated=True) ndb.IntegerProperty(repeated=True) ndb.KeyProperty(repeated=True) # etc. |
db.PhoneNumberProperty() |
ndb.StringProperty() |
db.PostalAddressProperty() |
ndb.StringProperty() |
db.RatingProperty() |
ndb.IntegerProperty() |
db.ReferenceProperty(AnotherModel) model_instance.prop MyModel.prop \ .get_value_for_datastore \ (model_instance) |
ndb.KeyProperty(kind=AnotherModel) model_instance.prop.get() model_instance.prop |
# Using the backreference set other = model_instance.prop other.prop_set.fetch(N) |
# No direct equivalent; emulation: other = model_instance.prop.get() MyModel.query( MyModel.prop == other.key).fetch(N) |
db.SelfReferenceProperty() |
ndb.KeyProperty(kind='ThisModelClass') |
db.StringProperty() |
ndb.StringProperty() |
db.StringProperty(multiline=True) |
Non compatible ; les chaînes sont toujours autorisées à contenir |
db.StringListProperty() |
ndb.StringProperty(repeated=True) |
db.TextProperty() |
ndb.TextProperty() |
db.TimeProperty() |
ndb.TimeProperty() |
db.UserProperty() |
ndb.UserProperty() |
blobstore.BlobReferenceProperty() |
ndb.BlobKeyProperty() |
Construire une clé
google.appengine.ext.db | ndb.model |
key = db.Key(encoded_key) |
key = ndb.Key(urlsafe=encoded_key) |
key = db.Key.from_path( 'MyKind', 'some_id', 'MyKind', 'some_id') |
key = ndb.Key( 'MyKind', 'some_id', 'MyKind', 'some_id') |
key = db.Key.from_path( MyModel, 'some_id', parent=model_instance, namespace='my_namespace') |
key = ndb.Key( MyModel, 'some_id', parent=model_instance.key, namespace='my_namespace') |
Opérations de clé
google.appengine.ext.db | ndb.model |
key.id_or_name() |
key.id() |
key.id() |
key.integer_id() |
key.name() |
key.string_id() |
key.has_id_or_name() |
key.id() is None # or... model_instance.has_complete_key() |
key.app(), key.namespace(), key.parent(), key.kind() |
Identique. |
str(key) |
key.urlsafe() |
key.to_path() |
key.flat() |
db.allocate_ids(MyModel, size) |
S, E = MyModel.allocate_ids(size) |
db.allocate_id_range(MyModel,X,Y) |
S, E = MyModel.allocate_ids(max=Y) assert S <= X |
Transactions
google.appengine.ext.db | ndb.model |
db.run_in_transaction(function) |
ndb.transaction(function) |
db.run_in_transaction( function, *args, **kwds) |
ndb.transaction( lambda: function(*args, **kwds)) |
db.run_in_transaction_custom_retries(n, function) |
ndb.transaction(function, retries=n) |
opts = \ db.create_transaction_options(xg=True) db.run_in_transaction_options(opts, fun) |
ndb.transaction(fun, xg=True) |
Requêtes
google.appengine.ext.db | ndb.model |
q = MyModel.all() |
q = MyModel.query() |
for result in q.run(): ... |
for result in q.iter(): ... |
q = MyModel.all() \ .filter('foo =', 'bar') \ .filter('baz >=', 'ding') |
q = MyModel.query( MyModel.foo == 'bar', MyModel.baz >= 'ding') |
q = MyModel.all() q.filter('foo =', 'bar') q.filter('baz >=', 'ding') q.order('-foo') results = q.fetch(10) |
q = MyModel.query() q = q.filter(MyModel.foo == 'bar') q = q.filter(MyModel.baz >= 'ding') q = q.order(-MyModel.foo) results = q.fetch(10) |
q.filter('__key__', k) # k is a db.Key instance |
q = q.filter(MyModel._key == k) # k is an ndb.Key instance |
a.filter('__key__ >=', k) # k is a db.Key instance |
q = q.filter(MyModel._key >= k) # k is an ndb.Key instance |
class MyExpando(Expando): pass q = MyExpando.all() q.filter('foo =', 'bar') |
class MyExpando(Expando): pass q = MyExpando.query( ndb.GenericProperty('foo') == 'bar') |
class Foo(Model): ... class Bar(Model): foo = ReferenceProperty(Foo) myfoo = <some Foo instance> for bar in myfoo.bar_set(): ... |
class Foo(Model): ... class Bar(Model): foo = KeyProperty(kind=Foo) myfoo = <some Foo instance> for bar in \ Bar.query(Bar.foo == myfoo.key): ... |
q = MyModel.all() q.ancestor(ancestor_key) |
q = MyModel.query(ancestor=ancestor_key) |
q = MyModel.all(keys_only=True) r = q.fetch(N) |
r = MyModel.query() \ .fetch(N, keys_only=True) # Alternatively: q = MyModel.query( default_options=QueryOptions( keys_only=True)) r = q.fetch(N) |
q = MyModel.gql(...) |
# same thing |
Curseurs
q = MyModel.all() a = q.fetch(20) cur = q.cursor() |
q = MyModel.query() a, cur, more = q.fetch_page(20) Dans NDB, |
q.with_cursor(cur) b = q.fetch(20) |
b, cur, more = \ q.fetch_page(20, start_cursor=cur) |
q.with_cursor(end_cursor=cur) b = q.fetch(20) |
q.fetch(20, end_cursor=cur) |