File: expressions.rst

package info (click to toggle)
python-django-postgres-extra 2.0.9-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 1,096 kB
  • sloc: python: 9,057; makefile: 17; sh: 7; sql: 1
file content (119 lines) | stat: -rw-r--r-- 3,174 bytes parent folder | download | duplicates (3)
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
.. include:: ./snippets/postgres_doc_links.rst
.. include:: ./snippets/manager_model_warning.rst

.. _expressions_page:

Expressions
===========


Selecting an individual HStore key
----------------------------------

Use the :class:`~psqlextra.expressions.HStoreRef` expression to select an indvidiual `hstore`_ key:

.. code-block:: python

   from psqlextra.models import PostgresModel
   from psqlextra.fields import HStoreField
   from psqlextra.expressions import HStoreRef

   class MyModel(PostgresModel):
      bla = HStoreField()

   MyModel.objects.create(bla={'a': '1', 'b': '2'})

   # '1'
   a = (
      MyModel.objects
      .annotate(a=HStoreRef('bla', 'a'))
      .values_list('a', flat=True)
      .first()
   )


Selecting a datetime as a UNIX epoch timestamp
----------------------------------------------

Use the :class:`~psqlextra.expressions.DateTimeEpoch` expression to select the value of a :class:`~django:django.db.models.DateTimeField` as a UNIX epoch timestamp.

.. code-block:: python

   from psqlextra.models import PostgresModel
   from psqlextra.fields import HStoreField
   from psqlextra.expressions import DateTimeEpoch

   class MyModel(PostgresModel):
      datetime = DateTimeField(auto_now_add=True)

   MyModel.objects.create()

   timestamp = (
      MyModel.objects
      .annotate(timestamp=DateTimeEpoch('datetime'))
      .values_list('timestamp', flat=True)
      .first()
   )


Multi-field coalesce
--------------------

Use the :class:`~psqlextra.expressions.IsNotNone` expression to perform something similar to a `coalesce`, but with multiple fields. The first non-null value encountered is selected.

.. code-block:: python

   from psqlextra.models import PostgresModel
   from psqlextra.fields import HStoreField
   from psqlextra.expressions import IsNotNone

   class MyModel(PostgresModel):
      name_1 = models.TextField(null=True)
      name_2 = models.TextField(null=True)
      name_3 = models.TextField(null=True)

   MyModel.objects.create(name_3='test')

   # 'test'
   name = (
      MyModel.objects
      .annotate(name=IsNotNone('name_1', 'name_2', 'name_3', default='buh'))
      .values_list('name', flat=True)
      .first()
   )

   # 'buh'
   name = (
      MyModel.objects
      .annotate(name=IsNotNone('name_1', 'name_2', default='buh'))
      .values_list('name', flat=True)
      .first()
   )


Excluded column
---------------

Use the :class:`~psqlextra.expressions.ExcludedCol` expression when performing an upsert using `ON CONFLICT`_ to refer to a column/field in the data is about to be upserted.

PostgreSQL keeps that data to be upserted in a special table named `EXCLUDED`. This expression is used to refer to a column in that table.

.. code-block:: python

    from django.db.models import Q
    from psqlextra.expressions import ExcludedCol

    (
        MyModel
        .objects
        .on_conflict(
            ['name'],
            ConflictAction.UPDATE,
            # translates to `priority > EXCLUDED.priority`
            update_condition=Q(priority__gt=ExcludedCol('priority')),
        )
        .insert(
            name='henk',
            priority=1,
        )
    )