Skip to main content

Bridge to enable using Django with Spanner.

Project description

This package provides a 3rd-party database backend for using Cloud Spanner with the Django ORM. It uses the Cloud Spanner Python client library under the hood.

Installation

To use this library, you’ll need a Google Cloud Platform project with the Cloud Spanner API enabled. For details on enabling the API and authenticating with GCP, see the Cloud Spanner Python client library quickstart guide.

Supported versions

At the moment, this library only supports Django 2.2. It also requires Python version 3.6 or later.

This package follows a common versioning convention for Django plugins: the major and minor version components of this package should match the installed version of Django. That is, django-google-spanner~=2.2 works with Django~=2.2.

Installing the package

To install from PyPI:

pip3 install django-google-spanner

To install from source:

git clone git@github.com:googleapis/python-spanner-django.git
cd python-spanner-django
pip3 install -e .

Creating a Cloud Spanner instance and database

If you don’t already have a Cloud Spanner database, or want to start from scratch for a new Django application, you can create a new instance and database using the Google Cloud SDK:

gcloud spanner instances create $INSTANCE --config=regional-us-central1 --description="New Django Instance" --nodes=1
gcloud spanner databases create $DB --instance $INSTANCE

Configuring settings.py

This package provides a Django application named django_spanner. To use the Cloud Spanner database backend, the application needs to installed and configured:

  • Add django_spanner as the first entry in INSTALLED_APPS:

    INSTALLED_APPS = [
        'django_spanner',
        ...
    ]
  • Edit the DATABASES setting to point to an existing Cloud Spanner database:

    DATABASES = {
        'default': {
            'ENGINE': 'django_spanner',
            'PROJECT': '$PROJECT',
            'INSTANCE': '$INSTANCE',
            'NAME': '$DATABASE',
        }
    }

How it works

Overall design

Internals

Executing a query

from google.cloud.spanner_dbapi import connect

connection = connect('<instance_id>', '<database_id>')
cursor = connection.cursor()

cursor.execute(
    "SELECT *"
    "FROM Singers"
    "WHERE SingerId = 15"
)

results = cursor.fetchall()

Contributing

Contributions to this library are always welcome and highly encouraged.

See [CONTRIBUTING][contributing] for more information on how to get started.

Please note that this project is released with a Contributor Code of Conduct. By participating in this project you agree to abide by its terms. See the Code of Conduct for more information.

Current limitations

AutoField generates random IDs

Spanner doesn’t have support for auto-generating primary key values. Therefore, django-google-spanner monkey-patches AutoField to generate a random UUID4. It generates a default using Field’s default option which means AutoFields will have a value when a model instance is created. For example:

>>> ExampleModel()
>>> ExampleModel.pk
4229421414948291880

To avoid hotspotting, these IDs are not monotonically increasing. This means that sorting models by ID isn’t guaranteed to return them in the order in which they were created.

ForeignKey constraints aren’t created (#313)

Spanner does not support ON DELETE CASCADE when creating foreign-key constraints, so this is not supported in django-google-spanner.

Check constraints aren’t supported

Spanner does not support CHECK constraints so one isn’t created for PositiveIntegerField and CheckConstraint can’t be used.

No native support for DecimalField

Spanner’s support for Decimal types is limited to NUMERIC precision. Higher-precision values can be stored as strings instead.

Meta.order_with_respect_to model option isn’t supported

This feature uses a column name that starts with an underscore (_order) which Spanner doesn’t allow.

Random QuerySet ordering isn’t supported

Spanner does not support it and will throw an exception. For example:

>>> ExampleModel.objects.order_by('?')
...
django.db.utils.ProgrammingError: 400 Function not found: RANDOM ... FROM
example_model ORDER BY RANDOM() ASC

Schema migrations

There are some limitations on schema changes to consider:

  • No support for renaming tables and columns;

  • A column’s type can’t be changed;

  • A table’s primary key can’t be altered.

DurationField arithmetic doesn’t work with DateField values (#253)

Spanner requires using different functions for arithmetic depending on the column type:

  • TIMESTAMP columns (DateTimeField) require TIMESTAMP_ADD or TIMESTAMP_SUB

  • DATE columns (DateField) require DATE_ADD or DATE_SUB

Django does not provide ways to determine which database function to use. DatabaseOperations.combine_duration_expression() arbitrarily uses TIMESTAMP_ADD and TIMESTAMP_SUB. Therefore, if you use a DateField in a DurationField expression, you’ll likely see an error such as:

"No matching signature for function TIMESTAMP\_ADD for argument types:
DATE, INTERVAL INT64 DATE\_TIME\_PART."

Computations that yield FLOAT64 values cannot be assigned to INT64 columns

Spanner does not support this (#331) and will throw an error:

>>> ExampleModel.objects.update(integer=F('integer') / 2)
...
django.db.utils.ProgrammingError: 400 Value of type FLOAT64 cannot be
assigned to integer, which has type INT64 [at 1:46]\nUPDATE
example_model SET integer = (example_model.integer /...

Addition with null values crash

Additions cannot include None values. For example:

>>> Book.objects.annotate(adjusted_rating=F('rating') + None)
...
google.api_core.exceptions.InvalidArgument: 400 Operands of + cannot be literal
NULL ...

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

django-google-spanner-2.2.1b1.tar.gz (59.2 kB view details)

Uploaded Source

Built Distribution

django_google_spanner-2.2.1b1-py3-none-any.whl (73.2 kB view details)

Uploaded Python 3

File details

Details for the file django-google-spanner-2.2.1b1.tar.gz.

File metadata

  • Download URL: django-google-spanner-2.2.1b1.tar.gz
  • Upload date:
  • Size: 59.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.4.1 importlib_metadata/4.5.0 pkginfo/1.7.0 requests/2.25.1 requests-toolbelt/0.9.1 tqdm/4.61.1 CPython/3.9.0

File hashes

Hashes for django-google-spanner-2.2.1b1.tar.gz
Algorithm Hash digest
SHA256 f20231a18324f3a79309bc5cdc03a73348952c5af076af1640c91925aa98f0d8
MD5 020a5f719b2557b303a54c55b04f6cc2
BLAKE2b-256 029d8755a396d5ba18900f920a8f49186dea775fc629d99943d50d45c2840b94

See more details on using hashes here.

File details

Details for the file django_google_spanner-2.2.1b1-py3-none-any.whl.

File metadata

  • Download URL: django_google_spanner-2.2.1b1-py3-none-any.whl
  • Upload date:
  • Size: 73.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.4.1 importlib_metadata/4.5.0 pkginfo/1.7.0 requests/2.25.1 requests-toolbelt/0.9.1 tqdm/4.61.1 CPython/3.9.0

File hashes

Hashes for django_google_spanner-2.2.1b1-py3-none-any.whl
Algorithm Hash digest
SHA256 adfb7144972527d148b001d30368339179822efba99967aeb3d9569312697f50
MD5 ed63fdca341b588d6cdfbf3c24bd3637
BLAKE2b-256 ca1a957286026a64b0fe90440985cc2f120e2b22228ff8d98059c545a52b658e

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page