Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Docs: updated README.rst file #563

Merged
merged 9 commits into from Dec 15, 2020
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
191 changes: 90 additions & 101 deletions README.rst
Expand Up @@ -5,20 +5,35 @@ ORM plugin for using Cloud Spanner as a `database backend
<https://docs.djangoproject.com/en/2.2/ref/databases/#using-a-3rd-party-database-backend>`__
for Django.

How it works
------------

Overall design
~~~~~~~~~~~~~~

.. figure:: ./assets/overview.png
:alt:

Internals
~~~~~~~~~

.. figure:: ./assets/internals.png
:alt:


Installation
------------

To use this library you'll need a Google Cloud Platform project with the Cloud
Spanner API enabled. See the `Cloud Spanner Python client docs
Using this library requires a Google Cloud Platform project with the Cloud
Spanner API enabled. See the Spanner' Python Client `documentation
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Spanner API enabled. See the Spanner' Python Client `documentation
Spanner API enabled. See the Spanner Python client `documentation

I'm no usage expert, but I think "Spanner" and "Python" are capitalized here as separate terms -- not as part of "Spanner Python Client" -- and "client" can be lowercase.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 Done.

<https://github.com/googleapis/python-spanner/#quick-start>`__ for details.

Use the version of ``django-google-spanner`` that corresponds to your version
The version of ``django-google-spanner`` must correspond to your version
of Django. For example, ``django-google-spanner`` 2.2.x works with Django
2.2.y. (This is the only supported version at this time.)
2.2.y (Note: this is the only supported version at this time).

The minor release number of Django doesn't correspond to the minor release
number of ``django-google-spanner``. Use the latest minor release of each.
The minor release numbers of Django may not correspond to the minor release
numbers of ``django-google-spanner``. Use the latest minor release of each.

To install from PyPI:

Expand All @@ -27,7 +42,7 @@ To install from PyPI:
pip3 install django-google-spanner


To install from source:
To install from the source:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
To install from the source:
To install from source:

"Install from source" actually sounds more natural to me. I was curious, but don't know that this proves anything:

image

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 Done!


.. code:: shell

Expand All @@ -39,12 +54,14 @@ To install from source:
Usage
-----

After `installation <#Installation>`__, you'll need to edit your Django
``settings.py`` file:
Configuring ``settings.py``
~~~~~~~~~~~~~~~~~~~~~~~~~~~

- Add ``django_spanner`` as the very first entry in the ``INSTALLED_APPS``
setting
After `installation <#Installation>`__, you'll have to update your Django
``settings.py`` file as follows.

- Add ``django_spanner`` as the very first entry in the ``INSTALLED_APPS``
settings:

.. code:: python

Expand All @@ -53,49 +70,43 @@ After `installation <#Installation>`__, you'll need to edit your Django
...
]

- Edit the ``DATABASES`` setting to point to an EXISTING database

Format
~~~~~~

.. code:: python

DATABASES = {
'default': {
'ENGINE': 'django_spanner',
'PROJECT': '<project_id>',
'INSTANCE': '<instance_id>',
'NAME': '<database_name>',
# Only include this if you need to specify where to retrieve the
# service account JSON for the credentials to connect to Cloud Spanner.
'OPTIONS': {
'credentials_uri': '<credentials_uri>',
},
},
}

Database configurations
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

.. code:: python
- Edit the ``DATABASES`` settings to point to an EXISTING database, as shown in the following example:

DATABASES = {
'default': {
'ENGINE': 'django_spanner',
'PROJECT': 'appdev-soda-spanner-staging', # Or the GCP project-id
'INSTANCE': 'django-dev1', # Or the Cloud Spanner instance
'NAME': 'db1', # Or the Cloud Spanner database to use
}
}
.. code:: python

Execute a query
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
DATABASES = {
'default': {
'ENGINE': 'django_spanner',
'PROJECT': '<GCP_project_id>',
'INSTANCE': '<instance_id>',
'NAME': '<database_name>',
}
}

- In order to retrieve the Cloud Spanner credentials from a JSON file, ``credentials_uri`` parameter can also be supplied in the ``OPTIONS`` field:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
- In order to retrieve the Cloud Spanner credentials from a JSON file, ``credentials_uri`` parameter can also be supplied in the ``OPTIONS`` field:
- In order to retrieve the Cloud Spanner credentials from a JSON file, the ``credentials_uri`` parameter can also be supplied in the ``OPTIONS`` field:

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done!


.. code:: python

DATABASES = {
'default': {
'ENGINE': 'django_spanner',
'PROJECT': '<GCP_project_id>',
'INSTANCE': '<instance_id>',
'NAME': '<database_name>',
'OPTIONS': {
'credentials_uri': '<credentials_uri>',
},
},
}

Executing a query
~~~~~~~~~~~~~~~~~

.. code:: python

from google.cloud.spanner_dbapi import connect

connection = connect("instance-id", "database-id")
connection = connect('<instance_id>', '<database_id>')
cursor = connection.cursor()

cursor.execute(
Expand All @@ -107,16 +118,8 @@ Execute a query
results = cur.fetchall()


Limitations
-----------

Transaction management isn't supported
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

``django-google-spanner`` always works in ``autocommit`` mode, which is
Django's default behavior even for backends that support manual transaction
management. Transactions cannot be controlled manually with calls like
``django.db.transaction.atomic()``.
Current limitations
-------------------

``AutoField`` generates random IDs
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Expand All @@ -139,34 +142,34 @@ 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
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
``ForeignKey`` constraints aren't created (`#313 <https://github.com/googleapis/python-spanner-django/issues/313>`__)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Spanner doesn't support ``ON DELETE CASCADE`` when creating foreign-key
constraints so ``django-google-spanner`` `doesn't support foreign key
constraints
<https://github.com/googleapis/python-spanner-django/issues/313>`__.
Spanner does not support ``ON DELETE CASCADE`` when creating foreign-key
constraints, so these are not supported in ``django-google-spanner``.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
constraints, so these are not supported in ``django-google-spanner``.
constraints, so this is not supported in ``django-google-spanner``.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 Done!


Check constraints aren't supported
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Spanner doesn't support ``CHECK`` constraints so one isn't created for
Spanner does not support ``CHECK`` constraints, so one isn't created for
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"Doesn't" get expanded by "isn't" doesn't?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 Done!

`PositiveIntegerField
<https://docs.djangoproject.com/en/stable/ref/models/fields/#positiveintegerfield>`__
and `CheckConstraint
<https://docs.djangoproject.com/en/stable/ref/models/constraints/#checkconstraint>`__
can't be used.

``DecimalField`` isn't supported
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
No native support for ``DecimalField``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Spanner doesn't support a NUMERIC data type that allows storing high
precision decimal values without the possibility of data loss.
Spanner's support for `Decimal <https://www.python.org/dev/peps/pep-0327/>`__
types is limited to
`NUMERIC <https://cloud.google.com/spanner/docs/data-types#numeric_types>`__
precision. Higher-precision values can be stored as strings instead.

``Variance`` and ``StdDev`` database functions aren't supported
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Spanner doesn't support these functions.
Spanner does not support these functions.

``Meta.order_with_respect_to`` model option isn't supported
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Expand All @@ -177,7 +180,7 @@ This feature uses a column name that starts with an underscore
Random ``QuerySet`` ordering isn't supported
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

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

::

Expand All @@ -189,13 +192,11 @@ Spanner doesn't support it. For example:
Schema migrations
~~~~~~~~~~~~~~~~~

Spanner has some limitations on schema changes which you must respect:
There are some limitations on schema changes to consider:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like this one has already been fixed.


- Renaming tables and columns isn't supported.
- A column's type can't be changed.
- No support for renaming tables and columns;
- A column's type can't be changed;
- A table's primary key can't be altered.
- Migrations aren't atomic since ``django-google-spanner`` doesn't support
transactions.

``DurationField`` arithmetic doesn't work with ``DateField`` values (`#253 <https://github.com/googleapis/python-spanner-django/issues/253>`__)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Expand All @@ -207,20 +208,23 @@ the column type:
or ``TIMESTAMP_SUB``
- ``DATE`` columns (``DateField``) require ``DATE_ADD`` or ``DATE_SUB``

Django doesn't provide a way to determine which database function to
use. ``DatabaseOperations.combine_duration_expression()`` arbitrary uses
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 see an error
like: "No matching signature for function TIMESTAMP\_ADD for argument
types: DATE, INTERVAL INT64 DATE\_TIME\_PART."
``DateField`` in a ``DurationField`` expression, you'll likely see an error
such as:

Computations that yield FLOAT64 values can't be assigned to INT64 columns
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
::

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

Spanner `doesn't support
this <https://github.com/googleapis/python-spanner-django/issues/331>`__.
Computations that yield FLOAT64 values cannot be assigned to INT64 columns
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

For example, if ``integer`` is ``IntegerField``:
Spanner does not support this (`#331
<https://github.com/googleapis/python-spanner-django/issues/331>`__) and will
throw an error:

::

Expand All @@ -233,26 +237,11 @@ For example, if ``integer`` is ``IntegerField``:
Addition with null values crash
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

For example:
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 ...

How it works
------------

Overall design
~~~~~~~~~~~~~~

.. figure:: ./assets/overview.png
:alt:

Internals
~~~~~~~~~

.. figure:: ./assets/internals.png
:alt:
2 changes: 1 addition & 1 deletion docs/api-reference.rst
@@ -1,6 +1,6 @@
API Reference
=============

The following classes and methods constitute the Spanner DB API connection.
The following classes and methods constitute the Django Spanner API.

[this page is under construction]
32 changes: 0 additions & 32 deletions docs/connection-usage.rst

This file was deleted.

4 changes: 4 additions & 0 deletions docs/django-spanner-usage.rst
@@ -0,0 +1,4 @@
Usage
=====

[this page is under construction]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's better to avoid checking "under construction" pages in, and just add them once they're written.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done!

2 changes: 1 addition & 1 deletion docs/index.rst
Expand Up @@ -6,7 +6,7 @@ Usage Documentation
:maxdepth: 1
:titlesonly:

connection-usage
django-spanner-usage

API Documentation
-----------------
Expand Down