Unverified Kaydet (Commit) 8b42a18b authored tarafından Mariusz Felisiak's avatar Mariusz Felisiak

[2.0.x] Refs #28643 -- Reorganized database functions docs.

Thanks Tim Graham for the review.

Backport of ad8036d7 from master
üst edd3601b
...@@ -23,8 +23,13 @@ We don't usually recommend allowing ``null=True`` for ``CharField`` since this ...@@ -23,8 +23,13 @@ We don't usually recommend allowing ``null=True`` for ``CharField`` since this
allows the field to have two "empty values", but it's important for the allows the field to have two "empty values", but it's important for the
``Coalesce`` example below. ``Coalesce`` example below.
.. _comparison-functions:
Comparison and conversion functions
===================================
``Cast`` ``Cast``
======== --------
.. class:: Cast(expression, output_field) .. class:: Cast(expression, output_field)
...@@ -40,7 +45,7 @@ Usage example:: ...@@ -40,7 +45,7 @@ Usage example::
4.0 4.0
``Coalesce`` ``Coalesce``
============ ------------
.. class:: Coalesce(*expressions, **extra) .. class:: Coalesce(*expressions, **extra)
...@@ -80,39 +85,8 @@ Usage examples:: ...@@ -80,39 +85,8 @@ Usage examples::
>>> now = timezone.now() >>> now = timezone.now()
>>> Coalesce('updated', Cast(now, DateTimeField())) >>> Coalesce('updated', Cast(now, DateTimeField()))
``Concat``
==========
.. class:: Concat(*expressions, **extra)
Accepts a list of at least two text fields or expressions and returns the
concatenated text. Each argument must be of a text or char type. If you want
to concatenate a ``TextField()`` with a ``CharField()``, then be sure to tell
Django that the ``output_field`` should be a ``TextField()``. Specifying an
``output_field`` is also required when concatenating a ``Value`` as in the
example below.
This function will never have a null result. On backends where a null argument
results in the entire expression being null, Django will ensure that each null
part is converted to an empty string first.
Usage example::
>>> # Get the display name as "name (goes_by)"
>>> from django.db.models import CharField, Value as V
>>> from django.db.models.functions import Concat
>>> Author.objects.create(name='Margaret Smith', goes_by='Maggie')
>>> author = Author.objects.annotate(
... screen_name=Concat(
... 'name', V(' ('), 'goes_by', V(')'),
... output_field=CharField()
... )
... ).get()
>>> print(author.screen_name)
Margaret Smith (Maggie)
``Greatest`` ``Greatest``
============ ------------
.. class:: Greatest(*expressions, **extra) .. class:: Greatest(*expressions, **extra)
...@@ -154,7 +128,7 @@ and ``comment.modified``. ...@@ -154,7 +128,7 @@ and ``comment.modified``.
a sensible minimum value to provide as a default. a sensible minimum value to provide as a default.
``Least`` ``Least``
========= ---------
.. class:: Least(*expressions, **extra) .. class:: Least(*expressions, **extra)
...@@ -175,148 +149,11 @@ will result in a database error. ...@@ -175,148 +149,11 @@ will result in a database error.
The PostgreSQL behavior can be emulated using ``Coalesce`` if you know The PostgreSQL behavior can be emulated using ``Coalesce`` if you know
a sensible maximum value to provide as a default. a sensible maximum value to provide as a default.
``Length`` .. _date-functions:
==========
.. class:: Length(expression, **extra)
Accepts a single text field or expression and returns the number of characters
the value has. If the expression is null, then the length will also be null.
Usage example::
>>> # Get the length of the name and goes_by fields
>>> from django.db.models.functions import Length
>>> Author.objects.create(name='Margaret Smith')
>>> author = Author.objects.annotate(
... name_length=Length('name'),
... goes_by_length=Length('goes_by')).get()
>>> print(author.name_length, author.goes_by_length)
(14, None)
It can also be registered as a transform. For example::
>>> from django.db.models import CharField Date functions
>>> from django.db.models.functions import Length
>>> CharField.register_lookup(Length, 'length')
>>> # Get authors whose name is longer than 7 characters
>>> authors = Author.objects.filter(name__length__gt=7)
``Lower``
=========
.. class:: Lower(expression, **extra)
Accepts a single text field or expression and returns the lowercase
representation.
It can also be registered as a transform as described in :class:`Length`.
Usage example::
>>> from django.db.models.functions import Lower
>>> Author.objects.create(name='Margaret Smith')
>>> author = Author.objects.annotate(name_lower=Lower('name')).get()
>>> print(author.name_lower)
margaret smith
``Now``
=======
.. class:: Now()
Returns the database server's current date and time when the query is executed,
typically using the SQL ``CURRENT_TIMESTAMP``.
Usage example::
>>> from django.db.models.functions import Now
>>> Article.objects.filter(published__lte=Now())
<QuerySet [<Article: How to Django>]>
.. admonition:: PostgreSQL considerations
On PostgreSQL, the SQL ``CURRENT_TIMESTAMP`` returns the time that the
current transaction started. Therefore for cross-database compatibility,
``Now()`` uses ``STATEMENT_TIMESTAMP`` instead. If you need the transaction
timestamp, use :class:`django.contrib.postgres.functions.TransactionNow`.
``StrIndex``
============
.. class:: StrIndex(string, substring, **extra)
.. versionadded:: 2.0
Returns a positive integer corresponding to the 1-indexed position of the first
occurrence of ``substring`` inside ``string``, or 0 if ``substring`` is not
found.
Usage example::
>>> from django.db.models import Value as V
>>> from django.db.models.functions import StrIndex
>>> Author.objects.create(name='Margaret Smith')
>>> Author.objects.create(name='Smith, Margaret')
>>> Author.objects.create(name='Margaret Jackson')
>>> Author.objects.filter(name='Margaret Jackson').annotate(
... smith_index=StrIndex('name', V('Smith'))
... ).get().smith_index
0
>>> authors = Author.objects.annotate(
... smith_index=StrIndex('name', V('Smith'))
... ).filter(smith_index__gt=0)
<QuerySet [<Author: Margaret Smith>, <Author: Smith, Margaret>]>
.. warning::
In MySQL, a database table's :ref:`collation<mysql-collation>` determines
whether string comparisons (such as the ``expression`` and ``substring`` of
this function) are case-sensitive. Comparisons are case-insensitive by
default.
``Substr``
==========
.. class:: Substr(expression, pos, length=None, **extra)
Returns a substring of length ``length`` from the field or expression starting
at position ``pos``. The position is 1-indexed, so the position must be greater
than 0. If ``length`` is ``None``, then the rest of the string will be returned.
Usage example::
>>> # Set the alias to the first 5 characters of the name as lowercase
>>> from django.db.models.functions import Substr, Lower
>>> Author.objects.create(name='Margaret Smith')
>>> Author.objects.update(alias=Lower(Substr('name', 1, 5)))
1
>>> print(Author.objects.get(name='Margaret Smith').alias)
marga
``Upper``
=========
.. class:: Upper(expression, **extra)
Accepts a single text field or expression and returns the uppercase
representation.
It can also be registered as a transform as described in :class:`Length`.
Usage example::
>>> from django.db.models.functions import Upper
>>> Author.objects.create(name='Margaret Smith')
>>> author = Author.objects.annotate(name_upper=Upper('name')).get()
>>> print(author.name_upper)
MARGARET SMITH
Date Functions
============== ==============
.. module:: django.db.models.functions.datetime
We'll be using the following model in examples of each function:: We'll be using the following model in examples of each function::
class Experiment(models.Model): class Experiment(models.Model):
...@@ -556,6 +393,26 @@ way, and takes priority over an active timezone:: ...@@ -556,6 +393,26 @@ way, and takes priority over an active timezone::
... ) ... )
{'day': 16, 'weekday': 3, 'hour': 9} {'day': 16, 'weekday': 3, 'hour': 9}
``Now``
-------
.. class:: Now()
Returns the database server's current date and time when the query is executed,
typically using the SQL ``CURRENT_TIMESTAMP``.
Usage example::
>>> from django.db.models.functions import Now
>>> Article.objects.filter(published__lte=Now())
<QuerySet [<Article: How to Django>]>
.. admonition:: PostgreSQL considerations
On PostgreSQL, the SQL ``CURRENT_TIMESTAMP`` returns the time that the
current transaction started. Therefore for cross-database compatibility,
``Now()`` uses ``STATEMENT_TIMESTAMP`` instead. If you need the transaction
timestamp, use :class:`django.contrib.postgres.functions.TransactionNow`.
``Trunc`` ``Trunc``
--------- ---------
...@@ -694,6 +551,76 @@ that deal with date-parts can be used with ``DateField``:: ...@@ -694,6 +551,76 @@ that deal with date-parts can be used with ``DateField``::
2016-01-01 00:00:00+11:00 1 2016-01-01 00:00:00+11:00 1
2014-06-01 00:00:00+10:00 1 2014-06-01 00:00:00+10:00 1
``DateTimeField`` truncation
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. class:: TruncDate(expression, **extra)
.. attribute:: lookup_name = 'date'
.. attribute:: output_field = DateField()
``TruncDate`` casts ``expression`` to a date rather than using the built-in SQL
truncate function. It's also registered as a transform on ``DateTimeField`` as
``__date``.
.. class:: TruncTime(expression, **extra)
.. versionadded:: 1.11
.. attribute:: lookup_name = 'time'
.. attribute:: output_field = TimeField()
``TruncTime`` casts ``expression`` to a time rather than using the built-in SQL
truncate function. It's also registered as a transform on ``DateTimeField`` as
``__time``.
.. class:: TruncDay(expression, output_field=None, tzinfo=None, **extra)
.. attribute:: kind = 'day'
.. class:: TruncHour(expression, output_field=None, tzinfo=None, **extra)
.. attribute:: kind = 'hour'
.. class:: TruncMinute(expression, output_field=None, tzinfo=None, **extra)
.. attribute:: kind = 'minute'
.. class:: TruncSecond(expression, output_field=None, tzinfo=None, **extra)
.. attribute:: kind = 'second'
These are logically equivalent to ``Trunc('datetime_field', kind)``. They
truncate all parts of the date up to ``kind`` and allow grouping or filtering
datetimes with less precision. ``expression`` must have an ``output_field`` of
``DateTimeField``.
Usage example::
>>> from datetime import date, datetime
>>> from django.db.models import Count
>>> from django.db.models.functions import (
... TruncDate, TruncDay, TruncHour, TruncMinute, TruncSecond,
... )
>>> from django.utils import timezone
>>> import pytz
>>> start1 = datetime(2014, 6, 15, 14, 30, 50, 321, tzinfo=timezone.utc)
>>> Experiment.objects.create(start_datetime=start1, start_date=start1.date())
>>> melb = pytz.timezone('Australia/Melbourne')
>>> Experiment.objects.annotate(
... date=TruncDate('start_datetime'),
... day=TruncDay('start_datetime', tzinfo=melb),
... hour=TruncHour('start_datetime', tzinfo=melb),
... minute=TruncMinute('start_datetime'),
... second=TruncSecond('start_datetime'),
... ).values('date', 'day', 'hour', 'minute', 'second').get()
{'date': datetime.date(2014, 6, 15),
'day': datetime.datetime(2014, 6, 16, 0, 0, tzinfo=<DstTzInfo 'Australia/Melbourne' AEST+10:00:00 STD>),
'hour': datetime.datetime(2014, 6, 16, 0, 0, tzinfo=<DstTzInfo 'Australia/Melbourne' AEST+10:00:00 STD>),
'minute': 'minute': datetime.datetime(2014, 6, 15, 14, 30, tzinfo=<UTC>),
'second': datetime.datetime(2014, 6, 15, 14, 30, 50, tzinfo=<UTC>)
}
``TimeField`` truncation ``TimeField`` truncation
~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~
...@@ -749,75 +676,157 @@ that deal with time-parts can be used with ``TimeField``:: ...@@ -749,75 +676,157 @@ that deal with time-parts can be used with ``TimeField``::
2014-06-16 00:00:00+10:00 2 2014-06-16 00:00:00+10:00 2
2016-01-01 04:00:00+11:00 1 2016-01-01 04:00:00+11:00 1
``DateTimeField`` truncation .. _text-functions:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. class:: TruncDate(expression, **extra) Text functions
==============
.. attribute:: lookup_name = 'date' ``Concat``
.. attribute:: output_field = DateField() ----------
``TruncDate`` casts ``expression`` to a date rather than using the built-in SQL .. class:: Concat(*expressions, **extra)
truncate function. It's also registered as a transform on ``DateTimeField`` as
``__date``.
.. class:: TruncTime(expression, **extra) Accepts a list of at least two text fields or expressions and returns the
concatenated text. Each argument must be of a text or char type. If you want
to concatenate a ``TextField()`` with a ``CharField()``, then be sure to tell
Django that the ``output_field`` should be a ``TextField()``. Specifying an
``output_field`` is also required when concatenating a ``Value`` as in the
example below.
.. versionadded:: 1.11 This function will never have a null result. On backends where a null argument
results in the entire expression being null, Django will ensure that each null
part is converted to an empty string first.
.. attribute:: lookup_name = 'time' Usage example::
.. attribute:: output_field = TimeField()
``TruncTime`` casts ``expression`` to a time rather than using the built-in SQL >>> # Get the display name as "name (goes_by)"
truncate function. It's also registered as a transform on ``DateTimeField`` as >>> from django.db.models import CharField, Value as V
``__time``. >>> from django.db.models.functions import Concat
>>> Author.objects.create(name='Margaret Smith', goes_by='Maggie')
>>> author = Author.objects.annotate(
... screen_name=Concat(
... 'name', V(' ('), 'goes_by', V(')'),
... output_field=CharField()
... )
... ).get()
>>> print(author.screen_name)
Margaret Smith (Maggie)
.. class:: TruncDay(expression, output_field=None, tzinfo=None, **extra) ``Length``
----------
.. attribute:: kind = 'day' .. class:: Length(expression, **extra)
.. class:: TruncHour(expression, output_field=None, tzinfo=None, **extra) Accepts a single text field or expression and returns the number of characters
the value has. If the expression is null, then the length will also be null.
.. attribute:: kind = 'hour' Usage example::
.. class:: TruncMinute(expression, output_field=None, tzinfo=None, **extra) >>> # Get the length of the name and goes_by fields
>>> from django.db.models.functions import Length
>>> Author.objects.create(name='Margaret Smith')
>>> author = Author.objects.annotate(
... name_length=Length('name'),
... goes_by_length=Length('goes_by')).get()
>>> print(author.name_length, author.goes_by_length)
(14, None)
.. attribute:: kind = 'minute' It can also be registered as a transform. For example::
.. class:: TruncSecond(expression, output_field=None, tzinfo=None, **extra) >>> from django.db.models import CharField
>>> from django.db.models.functions import Length
>>> CharField.register_lookup(Length, 'length')
>>> # Get authors whose name is longer than 7 characters
>>> authors = Author.objects.filter(name__length__gt=7)
.. attribute:: kind = 'second' ``Lower``
---------
These are logically equivalent to ``Trunc('datetime_field', kind)``. They .. class:: Lower(expression, **extra)
truncate all parts of the date up to ``kind`` and allow grouping or filtering
datetimes with less precision. ``expression`` must have an ``output_field`` of Accepts a single text field or expression and returns the lowercase
``DateTimeField``. representation.
It can also be registered as a transform as described in :class:`Length`.
Usage example:: Usage example::
>>> from datetime import date, datetime >>> from django.db.models.functions import Lower
>>> from django.db.models import Count >>> Author.objects.create(name='Margaret Smith')
>>> from django.db.models.functions import ( >>> author = Author.objects.annotate(name_lower=Lower('name')).get()
... TruncDate, TruncDay, TruncHour, TruncMinute, TruncSecond, >>> print(author.name_lower)
... ) margaret smith
>>> from django.utils import timezone
>>> import pytz ``StrIndex``
>>> start1 = datetime(2014, 6, 15, 14, 30, 50, 321, tzinfo=timezone.utc) ------------
>>> Experiment.objects.create(start_datetime=start1, start_date=start1.date())
>>> melb = pytz.timezone('Australia/Melbourne') .. class:: StrIndex(string, substring, **extra)
>>> Experiment.objects.annotate(
... date=TruncDate('start_datetime'), .. versionadded:: 2.0
... day=TruncDay('start_datetime', tzinfo=melb),
... hour=TruncHour('start_datetime', tzinfo=melb), Returns a positive integer corresponding to the 1-indexed position of the first
... minute=TruncMinute('start_datetime'), occurrence of ``substring`` inside ``string``, or 0 if ``substring`` is not
... second=TruncSecond('start_datetime'), found.
... ).values('date', 'day', 'hour', 'minute', 'second').get()
{'date': datetime.date(2014, 6, 15), Usage example::
'day': datetime.datetime(2014, 6, 16, 0, 0, tzinfo=<DstTzInfo 'Australia/Melbourne' AEST+10:00:00 STD>),
'hour': datetime.datetime(2014, 6, 16, 0, 0, tzinfo=<DstTzInfo 'Australia/Melbourne' AEST+10:00:00 STD>), >>> from django.db.models import Value as V
'minute': 'minute': datetime.datetime(2014, 6, 15, 14, 30, tzinfo=<UTC>), >>> from django.db.models.functions import StrIndex
'second': datetime.datetime(2014, 6, 15, 14, 30, 50, tzinfo=<UTC>) >>> Author.objects.create(name='Margaret Smith')
} >>> Author.objects.create(name='Smith, Margaret')
>>> Author.objects.create(name='Margaret Jackson')
>>> Author.objects.filter(name='Margaret Jackson').annotate(
... smith_index=StrIndex('name', V('Smith'))
... ).get().smith_index
0
>>> authors = Author.objects.annotate(
... smith_index=StrIndex('name', V('Smith'))
... ).filter(smith_index__gt=0)
<QuerySet [<Author: Margaret Smith>, <Author: Smith, Margaret>]>
.. warning::
In MySQL, a database table's :ref:`collation<mysql-collation>` determines
whether string comparisons (such as the ``expression`` and ``substring`` of
this function) are case-sensitive. Comparisons are case-insensitive by
default.
``Substr``
----------
.. class:: Substr(expression, pos, length=None, **extra)
Returns a substring of length ``length`` from the field or expression starting
at position ``pos``. The position is 1-indexed, so the position must be greater
than 0. If ``length`` is ``None``, then the rest of the string will be returned.
Usage example::
>>> # Set the alias to the first 5 characters of the name as lowercase
>>> from django.db.models.functions import Substr, Lower
>>> Author.objects.create(name='Margaret Smith')
>>> Author.objects.update(alias=Lower(Substr('name', 1, 5)))
1
>>> print(Author.objects.get(name='Margaret Smith').alias)
marga
``Upper``
---------
.. class:: Upper(expression, **extra)
Accepts a single text field or expression and returns the uppercase
representation.
It can also be registered as a transform as described in :class:`Length`.
Usage example::
>>> from django.db.models.functions import Upper
>>> Author.objects.create(name='Margaret Smith')
>>> author = Author.objects.annotate(name_upper=Upper('name')).get()
>>> print(author.name_upper)
MARGARET SMITH
.. _window-functions: .. _window-functions:
......
...@@ -423,12 +423,12 @@ Models ...@@ -423,12 +423,12 @@ Models
* A proxy model may now inherit multiple proxy models that share a common * A proxy model may now inherit multiple proxy models that share a common
non-abstract parent class. non-abstract parent class.
* Added :class:`~django.db.models.functions.datetime.Extract` functions * Added :class:`~django.db.models.functions.Extract` functions to extract
to extract datetime components as integers, such as year and hour. datetime components as integers, such as year and hour.
* Added :class:`~django.db.models.functions.datetime.Trunc` functions to * Added :class:`~django.db.models.functions.Trunc` functions to truncate a date
truncate a date or datetime to a significant component. They enable queries or datetime to a significant component. They enable queries like
like sales-per-day or sales-per-hour. sales-per-day or sales-per-hour.
* ``Model.__init__()`` now sets values of virtual fields from its keyword * ``Model.__init__()`` now sets values of virtual fields from its keyword
arguments. arguments.
...@@ -894,8 +894,8 @@ Miscellaneous ...@@ -894,8 +894,8 @@ Miscellaneous
yourself. yourself.
* Private expressions ``django.db.models.expressions.Date`` and ``DateTime`` * Private expressions ``django.db.models.expressions.Date`` and ``DateTime``
are removed. The new :class:`~django.db.models.functions.datetime.Trunc` are removed. The new :class:`~django.db.models.functions.Trunc` expressions
expressions provide the same functionality. provide the same functionality.
* The ``_base_manager`` and ``_default_manager`` attributes are removed from * The ``_base_manager`` and ``_default_manager`` attributes are removed from
model instances. They remain accessible on the model class. model instances. They remain accessible on the model class.
......
...@@ -330,16 +330,16 @@ Models ...@@ -330,16 +330,16 @@ Models
(This validator moved to the form field in :doc:`Django 1.11.2 <1.11.2>`.) (This validator moved to the form field in :doc:`Django 1.11.2 <1.11.2>`.)
* Added support for time truncation to * Added support for time truncation to
:class:`~django.db.models.functions.datetime.Trunc` functions. :class:`~django.db.models.functions.Trunc` functions.
* Added the :class:`~django.db.models.functions.datetime.ExtractWeek` function * Added the :class:`~django.db.models.functions.ExtractWeek` function to
to extract the week from :class:`~django.db.models.DateField` and extract the week from :class:`~django.db.models.DateField` and
:class:`~django.db.models.DateTimeField` and exposed it through the :class:`~django.db.models.DateTimeField` and exposed it through the
:lookup:`week` lookup. :lookup:`week` lookup.
* Added the :class:`~django.db.models.functions.datetime.TruncTime` function * Added the :class:`~django.db.models.functions.TruncTime` function to truncate
to truncate :class:`~django.db.models.DateTimeField` to its time component :class:`~django.db.models.DateTimeField` to its time component and exposed it
and exposed it through the :lookup:`time` lookup. through the :lookup:`time` lookup.
* Added support for expressions in :meth:`.QuerySet.values` and * Added support for expressions in :meth:`.QuerySet.values` and
:meth:`~.QuerySet.values_list`. :meth:`~.QuerySet.values_list`.
......
...@@ -245,20 +245,20 @@ Models ...@@ -245,20 +245,20 @@ Models
:attr:`Meta.get_latest_by <django.db.models.Options.get_latest_by>` now :attr:`Meta.get_latest_by <django.db.models.Options.get_latest_by>` now
allow ordering by several fields. allow ordering by several fields.
* Added the :class:`~django.db.models.functions.datetime.ExtractQuarter` * Added the :class:`~django.db.models.functions.ExtractQuarter` function to
function to extract the quarter from :class:`~django.db.models.DateField` and extract the quarter from :class:`~django.db.models.DateField` and
:class:`~django.db.models.DateTimeField`, and exposed it through the :class:`~django.db.models.DateTimeField`, and exposed it through the
:lookup:`quarter` lookup. :lookup:`quarter` lookup.
* Added the :class:`~django.db.models.functions.datetime.TruncQuarter` * Added the :class:`~django.db.models.functions.TruncQuarter` function to
function to truncate :class:`~django.db.models.DateField` and truncate :class:`~django.db.models.DateField` and
:class:`~django.db.models.DateTimeField` to the first day of a quarter. :class:`~django.db.models.DateTimeField` to the first day of a quarter.
* Added the :attr:`~django.db.models.Index.db_tablespace` parameter to * Added the :attr:`~django.db.models.Index.db_tablespace` parameter to
class-based indexes. class-based indexes.
* If the database supports a native duration field (Oracle and PostgreSQL), * If the database supports a native duration field (Oracle and PostgreSQL),
:class:`~django.db.models.functions.datetime.Extract` now works with :class:`~django.db.models.functions.Extract` now works with
:class:`~django.db.models.DurationField`. :class:`~django.db.models.DurationField`.
* Added the ``of`` argument to :meth:`.QuerySet.select_for_update()`, supported * Added the ``of`` argument to :meth:`.QuerySet.select_for_update()`, supported
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment