1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164
|
Django timescaledb
==================
A database backend and tooling for Timescaledb.
Based on
`gist <https://gist.github.com/dedsm/fc74f04eb70d78459ff0847ef16f2e7a>`__
from WeRiot.
Quick start
-----------
1. Install via pip
.. code:: bash
pip install django-timescaledb
2. Use as DATABASE engine in settings.py:
Standard PostgreSQL
.. code:: python
DATABASES = {
'default': {
'ENGINE': 'timescale.db.backends.postgresql',
...
},
}
PostGIS
.. code:: python
DATABASES = {
'default': {
'ENGINE': 'timescale.db.backends.postgis',
...
},
}
If you already make use of a custom PostgreSQL db backend you can set
the path in settings.py.
.. code:: python
TIMESCALE_DB_BACKEND_BASE = "django.contrib.gis.db.backends.postgis"
3. Inherit from the TimescaleModel. A
`hypertable <https://docs.timescale.com/latest/using-timescaledb/hypertables#react-docs>`__
will automatically be created.
.. code:: python
class TimescaleModel(models.Model):
"""
A helper class for using Timescale within Django, has the TimescaleManager and
TimescaleDateTimeField already present. This is an abstract class it should
be inheritted by another class for use.
"""
time = TimescaleDateTimeField(interval="1 day")
objects = TimescaleManager()
class Meta:
abstract = True
Implementation would look like this
.. code:: python
from timescale.db.models.models import TimescaleModel
class Metric(TimescaleModel):
temperature = models.FloatField()
If you already have a table, you can either add `time`
field of type `TimescaleDateTimeField` to your model or
rename (if not already named `time`) and change type of
existing `DateTimeField` (rename first then run
`makemigrations` and then change the type, so that
`makemigrations` considers it as change in same field
instead of removing and adding new field). This also
triggers the creation of a hypertable.
.. code:: python
from timescale.db.models.fields import TimescaleDateTimeField
from timescale.db.models.managers import TimescaleManager
class Metric(models.Model):
time = TimescaleDateTimeField(interval="1 day")
objects = models.Manager()
timescale = TimescaleManager()
The name of the field is important as Timescale specific feratures
require this as a property of their functions. ### Reading Data
"TimescaleDB hypertables are designed to behave in the same manner as
PostgreSQL database tables for reading data, using standard SQL
commands."
As such the use of the Django's ORM is perfectally suited to this type
of data. By leveraging a custom model manager and queryset we can extend
the queryset methods to include Timescale functions.
Time Bucket `More Info <https://docs.timescale.com/latest/using-timescaledb/reading-data#time-bucket>`__
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. code:: python
Metric.timescale.filter(time__range=date_range).time_bucket('time', '1 hour')
# expected output
<TimescaleQuerySet [{'bucket': datetime.datetime(2020, 12, 22, 11, 0, tzinfo=<UTC>)}, ... ]>
Time Bucket Gap Fill `More Info <https://docs.timescale.com/latest/using-timescaledb/reading-data#gap-filling>`__
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. code:: python
from metrics.models import *
from django.db.models import Count, Avg
from django.utils import timezone
from datetime import timedelta
ranges = (timezone.now() - timedelta(days=2), timezone.now())
(Metric.timescale
.filter(time__range=ranges)
.time_bucket_gapfill('time', '1 day', ranges[0], ranges[1], datapoints=240)
.annotate(Avg('temperature')))
# expected output
<TimescaleQuerySet [{'bucket': datetime.datetime(2020, 12, 21, 21, 24, tzinfo=<UTC>), 'temperature__avg': None}, ...]>
Histogram `More Info <https://docs.timescale.com/latest/using-timescaledb/reading-data#histogram>`__
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. code:: python
from metrics.models import *
from django.db.models import Count
from django.utils import timezone
from datetime import timedelta
ranges = (timezone.now() - timedelta(days=3), timezone.now())
(Metric.timescale
.filter(time__range=ranges)
.values('device')
.histogram(field='temperature', min_value=50.0, max_value=55.0, num_of_buckets=10)
.annotate(Count('device')))
# expected output
<TimescaleQuerySet [{'histogram': [0, 0, 0, 87, 93, 125, 99, 59, 0, 0, 0, 0], 'device__count': 463}]>
|