diff options
| author | Mariusz Felisiak <felisiak.mariusz@gmail.com> | 2017-10-13 18:20:11 +0200 |
|---|---|---|
| committer | Mariusz Felisiak <felisiak.mariusz@gmail.com> | 2017-10-13 18:38:50 +0200 |
| commit | 8b42a18b2d7bbd9e94ee80458a1cfcbb544e588c (patch) | |
| tree | 8d0130cfdc2cae9572437d259df52920ddaa85d2 | |
| parent | edd3601be6bedfcc52b3c628a444e1f878bc9adb (diff) | |
[2.0.x] Refs #28643 -- Reorganized database functions docs.
Thanks Tim Graham for the review.
Backport of ad8036d715d4447b95d485332511b4edb1a40c0e from master
| -rw-r--r-- | docs/ref/models/database-functions.txt | 457 | ||||
| -rw-r--r-- | docs/releases/1.10.txt | 14 | ||||
| -rw-r--r-- | docs/releases/1.11.txt | 12 | ||||
| -rw-r--r-- | docs/releases/2.0.txt | 10 |
4 files changed, 251 insertions, 242 deletions
diff --git a/docs/ref/models/database-functions.txt b/docs/ref/models/database-functions.txt index 410db7881c..2b7b652a4b 100644 --- a/docs/ref/models/database-functions.txt +++ b/docs/ref/models/database-functions.txt @@ -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 ``Coalesce`` example below. +.. _comparison-functions: + +Comparison and conversion functions +=================================== + ``Cast`` -======== +-------- .. class:: Cast(expression, output_field) @@ -40,7 +45,7 @@ Usage example:: 4.0 ``Coalesce`` -============ +------------ .. class:: Coalesce(*expressions, **extra) @@ -80,39 +85,8 @@ Usage examples:: >>> now = timezone.now() >>> 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`` -============ +------------ .. class:: Greatest(*expressions, **extra) @@ -154,7 +128,7 @@ and ``comment.modified``. a sensible minimum value to provide as a default. ``Least`` -========= +--------- .. class:: Least(*expressions, **extra) @@ -175,148 +149,11 @@ will result in a database error. The PostgreSQL behavior can be emulated using ``Coalesce`` if you know a sensible maximum value to provide as a default. -``Length`` -========== - -.. 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:: +.. _date-functions: - >>> 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) - -``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 +Date functions ============== -.. module:: django.db.models.functions.datetime - We'll be using the following model in examples of each function:: class Experiment(models.Model): @@ -556,6 +393,26 @@ way, and takes priority over an active timezone:: ... ) {'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`` --------- @@ -694,6 +551,76 @@ that deal with date-parts can be used with ``DateField``:: 2016-01-01 00:00:00+11: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 ~~~~~~~~~~~~~~~~~~~~~~~~ @@ -749,75 +676,157 @@ that deal with time-parts can be used with ``TimeField``:: 2014-06-16 00:00:00+10:00 2 2016-01-01 04:00:00+11:00 1 -``DateTimeField`` truncation -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +.. _text-functions: -.. class:: TruncDate(expression, **extra) +Text functions +============== - .. attribute:: lookup_name = 'date' - .. attribute:: output_field = DateField() +``Concat`` +---------- -``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:: Concat(*expressions, **extra) -.. 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' - .. attribute:: output_field = TimeField() +Usage example:: -``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``. + >>> # 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) -.. 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 -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``. +.. 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 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>) - } + >>> 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 + +``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 .. _window-functions: diff --git a/docs/releases/1.10.txt b/docs/releases/1.10.txt index b235afb4f5..4bfff75a63 100644 --- a/docs/releases/1.10.txt +++ b/docs/releases/1.10.txt @@ -423,12 +423,12 @@ Models * A proxy model may now inherit multiple proxy models that share a common non-abstract parent class. -* Added :class:`~django.db.models.functions.datetime.Extract` functions - to extract datetime components as integers, such as year and hour. +* Added :class:`~django.db.models.functions.Extract` functions to extract + datetime components as integers, such as year and hour. -* Added :class:`~django.db.models.functions.datetime.Trunc` functions to - truncate a date or datetime to a significant component. They enable queries - like sales-per-day or sales-per-hour. +* Added :class:`~django.db.models.functions.Trunc` functions to truncate a date + or datetime to a significant component. They enable queries like + sales-per-day or sales-per-hour. * ``Model.__init__()`` now sets values of virtual fields from its keyword arguments. @@ -894,8 +894,8 @@ Miscellaneous yourself. * Private expressions ``django.db.models.expressions.Date`` and ``DateTime`` - are removed. The new :class:`~django.db.models.functions.datetime.Trunc` - expressions provide the same functionality. + are removed. The new :class:`~django.db.models.functions.Trunc` expressions + provide the same functionality. * The ``_base_manager`` and ``_default_manager`` attributes are removed from model instances. They remain accessible on the model class. diff --git a/docs/releases/1.11.txt b/docs/releases/1.11.txt index 2a539441d5..ff4c1ebfef 100644 --- a/docs/releases/1.11.txt +++ b/docs/releases/1.11.txt @@ -330,16 +330,16 @@ Models (This validator moved to the form field in :doc:`Django 1.11.2 <1.11.2>`.) * 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 - to extract the week from :class:`~django.db.models.DateField` and +* Added the :class:`~django.db.models.functions.ExtractWeek` function to + extract the week from :class:`~django.db.models.DateField` and :class:`~django.db.models.DateTimeField` and exposed it through the :lookup:`week` lookup. -* Added the :class:`~django.db.models.functions.datetime.TruncTime` function - to truncate :class:`~django.db.models.DateTimeField` to its time component - and exposed it through the :lookup:`time` lookup. +* Added the :class:`~django.db.models.functions.TruncTime` function to truncate + :class:`~django.db.models.DateTimeField` to its time component and exposed it + through the :lookup:`time` lookup. * Added support for expressions in :meth:`.QuerySet.values` and :meth:`~.QuerySet.values_list`. diff --git a/docs/releases/2.0.txt b/docs/releases/2.0.txt index 1ee994b613..04ff9f5402 100644 --- a/docs/releases/2.0.txt +++ b/docs/releases/2.0.txt @@ -245,20 +245,20 @@ Models :attr:`Meta.get_latest_by <django.db.models.Options.get_latest_by>` now allow ordering by several fields. -* Added the :class:`~django.db.models.functions.datetime.ExtractQuarter` - function to extract the quarter from :class:`~django.db.models.DateField` and +* Added the :class:`~django.db.models.functions.ExtractQuarter` function to + extract the quarter from :class:`~django.db.models.DateField` and :class:`~django.db.models.DateTimeField`, and exposed it through the :lookup:`quarter` lookup. -* Added the :class:`~django.db.models.functions.datetime.TruncQuarter` - function to truncate :class:`~django.db.models.DateField` and +* Added the :class:`~django.db.models.functions.TruncQuarter` function to + truncate :class:`~django.db.models.DateField` and :class:`~django.db.models.DateTimeField` to the first day of a quarter. * Added the :attr:`~django.db.models.Index.db_tablespace` parameter to class-based indexes. * 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`. * Added the ``of`` argument to :meth:`.QuerySet.select_for_update()`, supported |
