An open API service indexing awesome lists of open source software.

https://github.com/cesbit/aiogcd

Async Google Cloud Datastore API
https://github.com/cesbit/aiogcd

asyncio google-cloud google-cloud-datastore orm-layer

Last synced: 3 months ago
JSON representation

Async Google Cloud Datastore API

Awesome Lists containing this project

README

          

[![CI](https://github.com/cesbit/aiogcd/workflows/CI/badge.svg)](https://github.com/cesbit/aiogcd/actions)
[![Release Version](https://img.shields.io/github/release/cesbit/aiogcd)](https://github.com/cesbit/aiogcd/releases)

Async Google Cloud Datastore API
================================
Package aiogcd includes both a Connector and ORM layer for communicating with Google Cloud Datastore without using App Engine.
> By design the connector has no dependencies to the ORM layer. This makes it possible to use the
connector without the orm layer if this is preferred.

---------------------------------------
* [Installation](#installation)
* [Connector](#connector)
* [Quick usage](#quick-usage)
* [Entity](#entity)
* [ORM](#orm-layer)
* [Namespaces](#namespaces)
* [Emulator](#emulater)

---------------------------------------

## Installation
The most easy way is to install this package using PyPI:
```
pip install aiogcd
```

To install from source code:
```
python setup.py install
```

## Connector
The connector is designed so that it can be used without using the ORM layer.

### Quick usage:

```python
import asyncio
from aiogcd.connector import GcdConnector

async def example():

# create a Google Cloud Datastore connector
gcd = GcdConnector(
project_id='my_project_id_or_app_id',
client_id='my_client_id',
client_secret='my_client_secret',
token_file='token_file.json')

# make at least one call to gcd using the connect() function. this function
# creates the token file in case it does not exists and might prompt the
# user for a code.
await gcd.connect()

asyncio.run(example())
```

### Entity

Create a new entity:

```python
import asyncio
from aiogcd.connector import GcdConnector
from aiogcd.connector.entity import Entity

async def insert_alice():
gcd = GcdConnector(
project_id='my_project_id_or_app_id',
client_id='my_client_id',
client_secret='my_client_secret',
token_file='token_file.json')

await gcd.connect()

alice = Entity({
'properties': {
'name': {'stringValue': 'Alice'},
'age': {'integerValue': 26}
},
'key': {
'partitionId': {'projectId': gcd.project_id},
'path': [{'kind': 'User'}]
}
})

await gcd.insert_entity(alice)

asyncio.run(insert_alice())

```

ORM Layer
=========

```python
import asyncio
from aiogcd.connector import GcdConnector
from aiogcd.connector.key import Key
from aiogcd.orm import GcdModel
from aiogcd.orm.properties import StringValue
from aiogcd.orm.properties import IntegerValue

# Create a GcdModel for kind 'User'
class User(GcdModel):
name = StringValue()
age = IntegerValue()

# If you want a model for a specific kind and use a different class name
# you can set __kind__ to the required kind name. For example:

# class UserModel(GcdModel):
# __kind__ = 'User'
# ...

# example insert
async def insert_alice():
# Create a key. As name/id we are allowed to use None since this is
# a new key. Gcd will assign a new id to the key.
key = Key('User', None, project_id=gcd.project_id)

# Create a new User entity.
alice = User(name='Alice', age=26, key=key)

# note that the key has no id assigned yet.
assert alice.key.id is None

# Insert the new entity.
await gcd.insert_entity(alice)

# The key now has an id assigned
assert isinstance(alice.key.id, int)

# return the key, we can use this later
return alice.key

# example query
async def query_users():
# query all user entities:
users = await User.filter().get_entities(gcd)

# create a Key from a key string:
key = Key(ks='')

# use the Key to get the User entity:
user = await User.filter(key=key).get_entity(gcd)

# get all user entities with name 'Bob' and age greater than 3
users = await User.filter(
User.name == 'Bob',
User.age > 3).get_entities(gcd)

# get all user entities with name 'Alice' and an ancestor key
users = await User.filter(
User.name == 'Alice',
has_ancestor= Key('Foo', 123)).get_entities(gcd)

# get all user entities with name 'Alice' and sort on age
users = await User.filter(
User.name == 'Alice'
).order_by(
User.age.ascending
).get_entities(gcd)

# get first 2 user entities with name 'Alice' and sort on age
users = await User.filter(
User.name == 'Alice'
).order_by(
User.age.ascending
).limit(2).get_entities(gcd)

# example update
async def update_age(ks, new_age):
# get the user by key string
user = await User.filter(key=Key(ks=ks)).get_entity(gcd)

# change the age
user.age = new_age

# save the changes
await gcd.update_entity(user)

gcd = GcdConnector(
project_id='my_project_id_or_app_id',
client_id='my_client_id',
client_secret='my_client_secret',
token_file='token_file.json')

asyncio.run(gcd.connect())
asyncio.run(insert_alice())
asyncio.run(query_users())
```

Namespaces
==========

As of version 0.11.4, aiogcd has support for namespaces. For using namespaces the `Key` and `GcdModel`

### Key

When initializing a key from a *key-string*, the `namespace_id` is automatically unpacked.
If instead a `path` is used, the namespace can be given using the `namespace_id=` keyword argument.

It is also possible to set the namespace using a dictionary, like in the example below:

```json
{
"partitionId": {
"projectId": "my-project-id",
"namespaceId": "my-namespace"
}
...
}
```

### GcdModel

If a `GcdModel` is used, it is possible to set the *namespace* on the model. For example:

```python
class Example(GcdModel):
__namespace__ = 'my-namespace'
```

With the above solution, queries like `Example.get_entities(gcd)` will automatically query the correct namespace.

As an alternative, the `GcdConnector` can be initialized using the `namespace_id=...` keyword argument.
If the `namespace_id` argument is used, all queries will use the given namespace unless explicitly overwritten by a `GcdModel`.

Emulator
========

The Google Datastore emulator is supported by `aiogcd` and thus reads the `DATASTORE_EMULATOR_HOST` environment variable.
Note that the `DATASTORE_PROJECT_ID` will be ignored and still needs to be set using the initialization of the `GcdConnector`.
See https://cloud.google.com/datastore/docs/tools/datastore-emulator for documentation on how to start the emulator.