database-functions.txt 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676
  1. ==================
  2. Database Functions
  3. ==================
  4. .. module:: django.db.models.functions
  5. :synopsis: Database Functions
  6. The classes documented below provide a way for users to use functions provided
  7. by the underlying database as annotations, aggregations, or filters in Django.
  8. Functions are also :doc:`expressions <expressions>`, so they can be used and
  9. combined with other expressions like :ref:`aggregate functions
  10. <aggregation-functions>`.
  11. We'll be using the following model in examples of each function::
  12. class Author(models.Model):
  13. name = models.CharField(max_length=50)
  14. age = models.PositiveIntegerField(null=True, blank=True)
  15. alias = models.CharField(max_length=50, null=True, blank=True)
  16. goes_by = models.CharField(max_length=50, null=True, blank=True)
  17. We don't usually recommend allowing ``null=True`` for ``CharField`` since this
  18. allows the field to have two "empty values", but it's important for the
  19. ``Coalesce`` example below.
  20. ``Cast``
  21. ========
  22. .. class:: Cast(expression, output_field)
  23. .. versionadded:: 1.10
  24. Forces the result type of ``expression`` to be the one from ``output_field``.
  25. Usage example::
  26. >>> from django.db.models import FloatField
  27. >>> from django.db.models.functions import Cast
  28. >>> Value.objects.create(integer=4)
  29. >>> value = Value.objects.annotate(as_float=Cast('integer', FloatField)).get()
  30. >>> print(value.as_float)
  31. 4.0
  32. ``Coalesce``
  33. ============
  34. .. class:: Coalesce(*expressions, **extra)
  35. Accepts a list of at least two field names or expressions and returns the
  36. first non-null value (note that an empty string is not considered a null
  37. value). Each argument must be of a similar type, so mixing text and numbers
  38. will result in a database error.
  39. Usage examples::
  40. >>> # Get a screen name from least to most public
  41. >>> from django.db.models import Sum, Value as V
  42. >>> from django.db.models.functions import Coalesce
  43. >>> Author.objects.create(name='Margaret Smith', goes_by='Maggie')
  44. >>> author = Author.objects.annotate(
  45. ... screen_name=Coalesce('alias', 'goes_by', 'name')).get()
  46. >>> print(author.screen_name)
  47. Maggie
  48. >>> # Prevent an aggregate Sum() from returning None
  49. >>> aggregated = Author.objects.aggregate(
  50. ... combined_age=Coalesce(Sum('age'), V(0)),
  51. ... combined_age_default=Sum('age'))
  52. >>> print(aggregated['combined_age'])
  53. 0
  54. >>> print(aggregated['combined_age_default'])
  55. None
  56. .. warning::
  57. A Python value passed to ``Coalesce`` on MySQL may be converted to an
  58. incorrect type unless explicitly cast to the correct database type:
  59. >>> from django.db.models.expressions import RawSQL
  60. >>> from django.utils import timezone
  61. >>> now = timezone.now()
  62. >>> now_sql = RawSQL("cast(%s as datetime)", (now,))
  63. >>> Coalesce('updated', now_sql)
  64. ``Concat``
  65. ==========
  66. .. class:: Concat(*expressions, **extra)
  67. Accepts a list of at least two text fields or expressions and returns the
  68. concatenated text. Each argument must be of a text or char type. If you want
  69. to concatenate a ``TextField()`` with a ``CharField()``, then be sure to tell
  70. Django that the ``output_field`` should be a ``TextField()``. This is also
  71. required when concatenating a ``Value`` as in the example below.
  72. This function will never have a null result. On backends where a null argument
  73. results in the entire expression being null, Django will ensure that each null
  74. part is converted to an empty string first.
  75. Usage example::
  76. >>> # Get the display name as "name (goes_by)"
  77. >>> from django.db.models import CharField, Value as V
  78. >>> from django.db.models.functions import Concat
  79. >>> Author.objects.create(name='Margaret Smith', goes_by='Maggie')
  80. >>> author = Author.objects.annotate(
  81. ... screen_name=Concat('name', V(' ('), 'goes_by', V(')'),
  82. ... output_field=CharField())).get()
  83. >>> print(author.screen_name)
  84. Margaret Smith (Maggie)
  85. ``Greatest``
  86. ============
  87. .. class:: Greatest(*expressions, **extra)
  88. Accepts a list of at least two field names or expressions and returns the
  89. greatest value. Each argument must be of a similar type, so mixing text and
  90. numbers will result in a database error.
  91. Usage example::
  92. class Blog(models.Model):
  93. body = models.TextField()
  94. modified = models.DateTimeField(auto_now=True)
  95. class Comment(models.Model):
  96. body = models.TextField()
  97. modified = models.DateTimeField(auto_now=True)
  98. blog = models.ForeignKey(Blog, on_delete=models.CASCADE)
  99. >>> from django.db.models.functions import Greatest
  100. >>> blog = Blog.objects.create(body='Greatest is the best.')
  101. >>> comment = Comment.objects.create(body='No, Least is better.', blog=blog)
  102. >>> comments = Comment.objects.annotate(last_updated=Greatest('modified', 'blog__modified'))
  103. >>> annotated_comment = comments.get()
  104. ``annotated_comment.last_updated`` will be the most recent of ``blog.modified``
  105. and ``comment.modified``.
  106. .. warning::
  107. The behavior of ``Greatest`` when one or more expression may be ``null``
  108. varies between databases:
  109. - PostgreSQL: ``Greatest`` will return the largest non-null expression,
  110. or ``null`` if all expressions are ``null``.
  111. - SQLite, Oracle, and MySQL: If any expression is ``null``, ``Greatest``
  112. will return ``null``.
  113. The PostgreSQL behavior can be emulated using ``Coalesce`` if you know
  114. a sensible minimum value to provide as a default.
  115. ``Least``
  116. =========
  117. .. class:: Least(*expressions, **extra)
  118. Accepts a list of at least two field names or expressions and returns the
  119. least value. Each argument must be of a similar type, so mixing text and numbers
  120. will result in a database error.
  121. .. warning::
  122. The behavior of ``Least`` when one or more expression may be ``null``
  123. varies between databases:
  124. - PostgreSQL: ``Least`` will return the smallest non-null expression,
  125. or ``null`` if all expressions are ``null``.
  126. - SQLite, Oracle, and MySQL: If any expression is ``null``, ``Least``
  127. will return ``null``.
  128. The PostgreSQL behavior can be emulated using ``Coalesce`` if you know
  129. a sensible maximum value to provide as a default.
  130. ``Length``
  131. ==========
  132. .. class:: Length(expression, **extra)
  133. Accepts a single text field or expression and returns the number of characters
  134. the value has. If the expression is null, then the length will also be null.
  135. Usage example::
  136. >>> # Get the length of the name and goes_by fields
  137. >>> from django.db.models.functions import Length
  138. >>> Author.objects.create(name='Margaret Smith')
  139. >>> author = Author.objects.annotate(
  140. ... name_length=Length('name'),
  141. ... goes_by_length=Length('goes_by')).get()
  142. >>> print(author.name_length, author.goes_by_length)
  143. (14, None)
  144. It can also be registered as a transform. For example::
  145. >>> from django.db.models import CharField
  146. >>> from django.db.models.functions import Length
  147. >>> CharField.register_lookup(Length, 'length')
  148. >>> # Get authors whose name is longer than 7 characters
  149. >>> authors = Author.objects.filter(name__length__gt=7)
  150. ``Lower``
  151. =========
  152. .. class:: Lower(expression, **extra)
  153. Accepts a single text field or expression and returns the lowercase
  154. representation.
  155. It can also be registered as a transform as described in :class:`Length`.
  156. Usage example::
  157. >>> from django.db.models.functions import Lower
  158. >>> Author.objects.create(name='Margaret Smith')
  159. >>> author = Author.objects.annotate(name_lower=Lower('name')).get()
  160. >>> print(author.name_lower)
  161. margaret smith
  162. ``Now``
  163. =======
  164. .. class:: Now()
  165. Returns the database server's current date and time when the query is executed,
  166. typically using the SQL ``CURRENT_TIMESTAMP``.
  167. Usage example::
  168. >>> from django.db.models.functions import Now
  169. >>> Article.objects.filter(published__lte=Now())
  170. <QuerySet [<Article: How to Django>]>
  171. .. admonition:: PostgreSQL considerations
  172. On PostgreSQL, the SQL ``CURRENT_TIMESTAMP`` returns the time that the
  173. current transaction started. Therefore for cross-database compatibility,
  174. ``Now()`` uses ``STATEMENT_TIMESTAMP`` instead. If you need the transaction
  175. timestamp, use :class:`django.contrib.postgres.functions.TransactionNow`.
  176. ``Substr``
  177. ==========
  178. .. class:: Substr(expression, pos, length=None, **extra)
  179. Returns a substring of length ``length`` from the field or expression starting
  180. at position ``pos``. The position is 1-indexed, so the position must be greater
  181. than 0. If ``length`` is ``None``, then the rest of the string will be returned.
  182. Usage example::
  183. >>> # Set the alias to the first 5 characters of the name as lowercase
  184. >>> from django.db.models.functions import Substr, Lower
  185. >>> Author.objects.create(name='Margaret Smith')
  186. >>> Author.objects.update(alias=Lower(Substr('name', 1, 5)))
  187. 1
  188. >>> print(Author.objects.get(name='Margaret Smith').alias)
  189. marga
  190. ``Upper``
  191. =========
  192. .. class:: Upper(expression, **extra)
  193. Accepts a single text field or expression and returns the uppercase
  194. representation.
  195. It can also be registered as a transform as described in :class:`Length`.
  196. Usage example::
  197. >>> from django.db.models.functions import Upper
  198. >>> Author.objects.create(name='Margaret Smith')
  199. >>> author = Author.objects.annotate(name_upper=Upper('name')).get()
  200. >>> print(author.name_upper)
  201. MARGARET SMITH
  202. Date Functions
  203. ==============
  204. .. module:: django.db.models.functions.datetime
  205. .. versionadded:: 1.10
  206. We'll be using the following model in examples of each function::
  207. class Experiment(models.Model):
  208. start_time = models.DateTimeField()
  209. start_date = models.DateField(null=True, blank=True)
  210. end_time = models.DateTimeField(null=True, blank=True)
  211. end_date = models.DateField(null=True, blank=True)
  212. ``Extract``
  213. -----------
  214. .. class:: Extract(expression, lookup_name=None, tzinfo=None, **extra)
  215. Extracts a component of a date as a number.
  216. Takes an ``expression`` representing a ``DateField`` or ``DateTimeField`` and a
  217. ``lookup_name``, and returns the part of the date referenced by ``lookup_name``
  218. as an ``IntegerField``. Django usually uses the databases' extract function, so
  219. you may use any ``lookup_name`` that your database supports. A ``tzinfo``
  220. subclass, usually provided by ``pytz``, can be passed to extract a value in a
  221. specific timezone.
  222. Given the datetime ``2015-06-15 23:30:01.000321+00:00``, the built-in
  223. ``lookup_name``\s return:
  224. * "year": 2015
  225. * "month": 6
  226. * "day": 15
  227. * "week_day": 2
  228. * "hour": 23
  229. * "minute": 30
  230. * "second": 1
  231. If a different timezone like ``Australia/Melbourne`` is active in Django, then
  232. the datetime is converted to the timezone before the value is extracted. The
  233. timezone offset for Melbourne in the example date above is +10:00. The values
  234. returned when this timezone is active will be the same as above except for:
  235. * "day": 16
  236. * "week_day": 3
  237. * "hour": 9
  238. .. admonition:: ``week_day`` values
  239. The ``week_day`` ``lookup_type`` is calculated differently from most
  240. databases and from Python's standard functions. This function will return
  241. ``1`` for Sunday, ``2`` for Monday, through ``7`` for Saturday.
  242. The equivalent calculation in Python is::
  243. >>> from datetime import datetime
  244. >>> dt = datetime(2015, 6, 15)
  245. >>> (dt.isoweekday() % 7) + 1
  246. 2
  247. Each ``lookup_name`` above has a corresponding ``Extract`` subclass (listed
  248. below) that should typically be used instead of the more verbose equivalent,
  249. e.g. use ``ExtractYear(...)`` rather than ``Extract(..., lookup_name='year')``.
  250. Usage example::
  251. >>> from datetime import datetime
  252. >>> from django.db.models.functions import Extract
  253. >>> start = datetime(2015, 6, 15)
  254. >>> end = datetime(2015, 7, 2)
  255. >>> Experiment.objects.create(
  256. ... start_time=start, start_date=start.date(),
  257. ... end_time=end, end_date=end.date())
  258. >>> # Add the experiment start year as a field in the QuerySet.
  259. >>> experiment = Experiment.objects.annotate(
  260. ... start_year=Extract('start_time', 'year')).get()
  261. >>> experiment.start_year
  262. 2015
  263. >>> # How many experiments completed in the same year in which they started?
  264. >>> Experiment.objects.filter(
  265. ... start_time__year=Extract('end_time', 'year')).count()
  266. 1
  267. ``DateField`` extracts
  268. ~~~~~~~~~~~~~~~~~~~~~~
  269. .. class:: ExtractYear(expression, tzinfo=None, **extra)
  270. .. attribute:: lookup_name = 'year'
  271. .. class:: ExtractMonth(expression, tzinfo=None, **extra)
  272. .. attribute:: lookup_name = 'month'
  273. .. class:: ExtractDay(expression, tzinfo=None, **extra)
  274. .. attribute:: lookup_name = 'day'
  275. .. class:: ExtractWeekDay(expression, tzinfo=None, **extra)
  276. .. attribute:: lookup_name = 'week_day'
  277. These are logically equivalent to ``Extract('date_field', lookup_name)``. Each
  278. class is also a ``Transform`` registered on ``DateField`` and ``DateTimeField``
  279. as ``__(lookup_name)``, e.g. ``__year``.
  280. Since ``DateField``\s don't have a time component, only ``Extract`` subclasses
  281. that deal with date-parts can be used with ``DateField``::
  282. >>> from datetime import datetime
  283. >>> from django.utils import timezone
  284. >>> from django.db.models.functions import (
  285. ... ExtractYear, ExtractMonth, ExtractDay, ExtractWeekDay
  286. ... )
  287. >>> start_2015 = datetime(2015, 6, 15, 23, 30, 1, tzinfo=timezone.utc)
  288. >>> end_2015 = datetime(2015, 6, 16, 13, 11, 27, tzinfo=timezone.utc)
  289. >>> Experiment.objects.create(
  290. ... start_time=start_2015, start_date=start_2015.date(),
  291. ... end_time=end_2015, end_date=end_2015.date())
  292. >>> Experiment.objects.annotate(
  293. ... year=ExtractYear('start_date'),
  294. ... month=ExtractMonth('start_date'),
  295. ... day=ExtractDay('start_date'),
  296. ... weekday=ExtractWeekDay('start_date'),
  297. ... ).values('year', 'month', 'day', 'weekday').get(
  298. ... end_date__year=ExtractYear('start_date'),
  299. ... )
  300. {'year': 2015, 'month': 6, 'day': 15, 'weekday': 2}
  301. ``DateTimeField`` extracts
  302. ~~~~~~~~~~~~~~~~~~~~~~~~~~
  303. In addition to the following, all extracts for ``DateField`` listed above may
  304. also be used on ``DateTimeField``\s .
  305. .. class:: ExtractHour(expression, tzinfo=None, **extra)
  306. .. attribute:: lookup_name = 'hour'
  307. .. class:: ExtractMinute(expression, tzinfo=None, **extra)
  308. .. attribute:: lookup_name = 'minute'
  309. .. class:: ExtractSecond(expression, tzinfo=None, **extra)
  310. .. attribute:: lookup_name = 'second'
  311. These are logically equivalent to ``Extract('datetime_field', lookup_name)``.
  312. Each class is also a ``Transform`` registered on ``DateTimeField`` as
  313. ``__(lookup_name)``, e.g. ``__minute``.
  314. ``DateTimeField`` examples::
  315. >>> from datetime import datetime
  316. >>> from django.utils import timezone
  317. >>> from django.db.models.functions import (
  318. ... ExtractYear, ExtractMonth, ExtractDay, ExtractWeekDay,
  319. ... ExtractHour, ExtractMinute, ExtractSecond,
  320. ... )
  321. >>> start_2015 = datetime(2015, 6, 15, 23, 30, 1, tzinfo=timezone.utc)
  322. >>> end_2015 = datetime(2015, 6, 16, 13, 11, 27, tzinfo=timezone.utc)
  323. >>> Experiment.objects.create(
  324. ... start_time=start_2015, start_date=start_2015.date(),
  325. ... end_time=end_2015, end_date=end_2015.date())
  326. >>> Experiment.objects.annotate(
  327. ... year=ExtractYear('start_time'),
  328. ... month=ExtractMonth('start_time'),
  329. ... day=ExtractDay('start_time'),
  330. ... weekday=ExtractWeekDay('start_time'),
  331. ... hour=ExtractHour('start_time'),
  332. ... minute=ExtractMinute('start_time'),
  333. ... second=ExtractSecond('start_time'),
  334. ... ).values(
  335. ... 'year', 'month', 'day', 'weekday', 'hour', 'minute', 'second',
  336. ... ).get(end_time__year=ExtractYear('start_time'))
  337. {'year': 2015, 'month': 6, 'day': 15, 'weekday': 2, 'hour': 23, 'minute': 30, 'second': 1}
  338. When :setting:`USE_TZ` is ``True`` then datetimes are stored in the database
  339. in UTC. If a different timezone is active in Django, the datetime is converted
  340. to that timezone before the value is extracted. The example below converts to
  341. the Melbourne timezone (UTC +10:00), which changes the day, weekday, and hour
  342. values that are returned::
  343. >>> import pytz
  344. >>> tzinfo = pytz.timezone('Australia/Melbourne') # UTC+10:00
  345. >>> with timezone.override(tzinfo):
  346. ... Experiment.objects.annotate(
  347. ... day=ExtractDay('start_time'),
  348. ... weekday=ExtractWeekDay('start_time'),
  349. ... hour=ExtractHour('start_time'),
  350. ... ).values('day', 'weekday', 'hour').get(
  351. ... end_time__year=ExtractYear('start_time'),
  352. ... )
  353. {'day': 16, 'weekday': 3, 'hour': 9}
  354. Explicitly passing the timezone to the ``Extract`` function behaves in the same
  355. way, and takes priority over an active timezone::
  356. >>> import pytz
  357. >>> tzinfo = pytz.timezone('Australia/Melbourne')
  358. >>> Experiment.objects.annotate(
  359. ... day=ExtractDay('start_time', tzinfo=melb),
  360. ... weekday=ExtractWeekDay('start_time', tzinfo=melb),
  361. ... hour=ExtractHour('start_time', tzinfo=melb),
  362. ... ).values('day', 'weekday', 'hour').get(
  363. ... end_time__year=ExtractYear('start_time'),
  364. ... )
  365. {'day': 16, 'weekday': 3, 'hour': 9}
  366. ``Trunc``
  367. ---------
  368. .. class:: Trunc(expression, kind, output_field=None, tzinfo=None, **extra)
  369. Truncates a date up to a significant component.
  370. When you only care if something happened in a particular year, hour, or day,
  371. but not the exact second, then ``Trunc`` (and its subclasses) can be useful to
  372. filter or aggregate your data. For example, you can use ``Trunc`` to calculate
  373. the number of sales per day.
  374. ``Trunc`` takes a single ``expression``, representing a ``DateField`` or
  375. ``DateTimeField``, a ``kind`` representing a date part, and an ``output_field``
  376. that's either ``DateTimeField()`` or ``DateField()``. It returns a datetime or
  377. date, depending on ``output_field``, with fields up to ``kind`` set to their
  378. minimum value. If ``output_field`` is omitted, it will default to the
  379. ``output_field`` of ``expression``. A ``tzinfo`` subclass, usually provided by
  380. ``pytz``, can be passed to truncate a value in a specific timezone.
  381. Given the datetime ``2015-06-15 14:30:50.000321+00:00``, the built-in ``kind``\s
  382. return:
  383. * "year": 2015-01-01 00:00:00+00:00
  384. * "month": 2015-06-01 00:00:00+00:00
  385. * "day": 2015-06-15 00:00:00+00:00
  386. * "hour": 2015-06-15 14:00:00+00:00
  387. * "minute": 2015-06-15 14:30:00+00:00
  388. * "second": 2015-06-15 14:30:50+00:00
  389. If a different timezone like ``Australia/Melbourne`` is active in Django, then
  390. the datetime is converted to the new timezone before the value is truncated.
  391. The timezone offset for Melbourne in the example date above is +10:00. The
  392. values returned when this timezone is active will be:
  393. * "year": 2015-01-01 00:00:00+11:00
  394. * "month": 2015-06-01 00:00:00+10:00
  395. * "day": 2015-06-16 00:00:00+10:00
  396. * "hour": 2015-06-16 00:00:00+10:00
  397. * "minute": 2015-06-16 00:30:00+10:00
  398. * "second": 2015-06-16 00:30:50+10:00
  399. The year has an offset of +11:00 because the result transitioned into daylight
  400. saving time.
  401. Each ``kind`` above has a corresponding ``Trunc`` subclass (listed below) that
  402. should typically be used instead of the more verbose equivalent,
  403. e.g. use ``TruncYear(...)`` rather than ``Trunc(..., kind='year')``.
  404. The subclasses are all defined as transforms, but they aren't registered with
  405. any fields, because the obvious lookup names are already reserved by the
  406. ``Extract`` subclasses.
  407. Usage example::
  408. >>> from datetime import datetime
  409. >>> from django.db.models import Count, DateTimeField
  410. >>> from django.db.models.functions import Trunc
  411. >>> Experiment.objects.create(start_time=datetime(2015, 6, 15, 14, 30, 50, 321))
  412. >>> Experiment.objects.create(start_time=datetime(2015, 6, 15, 14, 40, 2, 123))
  413. >>> Experiment.objects.create(start_time=datetime(2015, 12, 25, 10, 5, 27, 999))
  414. >>> experiments_per_day = Experiment.objects.annotate(
  415. ... start_day=Trunc('start_time', 'day', output_field=DateTimeField())
  416. ... ).values('start_day').annotate(experiments=Count('id'))
  417. >>> for exp in experiments_per_day:
  418. ... print(exp['start_day'], exp['experiments'])
  419. ...
  420. 2015-06-15 00:00:00 2
  421. 2015-12-25 00:00:00 1
  422. >>> experiments = Experiment.objects.annotate(
  423. ... start_day=Trunc('start_time', 'day', output_field=DateTimeField())
  424. ... ).filter(start_day=datetime(2015, 6, 15))
  425. >>> for exp in experiments:
  426. ... print(exp.start_time)
  427. ...
  428. 2015-06-15 14:30:50.000321
  429. 2015-06-15 14:40:02.000123
  430. ``DateField`` truncation
  431. ~~~~~~~~~~~~~~~~~~~~~~~~
  432. .. class:: TruncYear(expression, output_field=None, tzinfo=None, **extra)
  433. .. attribute:: kind = 'year'
  434. .. class:: TruncMonth(expression, output_field=None, tzinfo=None, **extra)
  435. .. attribute:: kind = 'month'
  436. These are logically equivalent to ``Trunc('date_field', kind)``. They truncate
  437. all parts of the date up to ``kind`` which allows grouping or filtering dates
  438. with less precision. ``expression`` can have an ``output_field`` of either
  439. ``DateField`` or ``DateTimeField``.
  440. Since ``DateField``\s don't have a time component, only ``Trunc`` subclasses
  441. that deal with date-parts can be used with ``DateField``::
  442. >>> from datetime import datetime
  443. >>> from django.db.models import Count
  444. >>> from django.db.models.functions import TruncMonth, TruncYear
  445. >>> from django.utils import timezone
  446. >>> start1 = datetime(2014, 6, 15, 14, 30, 50, 321, tzinfo=timezone.utc)
  447. >>> start2 = datetime(2015, 6, 15, 14, 40, 2, 123, tzinfo=timezone.utc)
  448. >>> start3 = datetime(2015, 12, 31, 17, 5, 27, 999, tzinfo=timezone.utc)
  449. >>> Experiment.objects.create(start_time=start1, start_date=start1.date())
  450. >>> Experiment.objects.create(start_time=start2, start_date=start2.date())
  451. >>> Experiment.objects.create(start_time=start3, start_date=start3.date())
  452. >>> experiments_per_year = Experiment.objects.annotate(
  453. ... year=TruncYear('start_date')).values('year').annotate(
  454. ... experiments=Count('id'))
  455. >>> for exp in experiments_per_year:
  456. ... print(exp['year'], exp['experiments'])
  457. ...
  458. 2014-01-01 1
  459. 2015-01-01 2
  460. >>> import pytz
  461. >>> melb = pytz.timezone('Australia/Melbourne')
  462. >>> experiments_per_month = Experiment.objects.annotate(
  463. ... month=TruncMonth('start_time', tzinfo=melb)).values('month').annotate(
  464. ... experiments=Count('id'))
  465. >>> for exp in experiments_per_month:
  466. ... print(exp['month'], exp['experiments'])
  467. ...
  468. 2015-06-01 00:00:00+10:00 1
  469. 2016-01-01 00:00:00+11:00 1
  470. 2014-06-01 00:00:00+10:00 1
  471. ``DateTimeField`` truncation
  472. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  473. .. class:: TruncDate(expression, **extra)
  474. .. attribute:: lookup_name = 'date'
  475. .. attribute:: output_field = DateField()
  476. ``TruncDate`` casts ``expression`` to a date rather than using the built-in SQL
  477. truncate function. It's also registered as a transform on ``DateTimeField`` as
  478. ``__date``.
  479. .. class:: TruncDay(expression, output_field=None, tzinfo=None, **extra)
  480. .. attribute:: kind = 'day'
  481. .. class:: TruncHour(expression, output_field=None, tzinfo=None, **extra)
  482. .. attribute:: kind = 'hour'
  483. .. class:: TruncMinute(expression, output_field=None, tzinfo=None, **extra)
  484. .. attribute:: kind = 'minute'
  485. .. class:: TruncSecond(expression, output_field=None, tzinfo=None, **extra)
  486. .. attribute:: kind = 'second'
  487. These are logically equivalent to ``Trunc('datetime_field', kind)``. They
  488. truncate all parts of the date up to ``kind`` and allow grouping or filtering
  489. datetimes with less precision. ``expression`` must have an ``output_field`` of
  490. ``DateTimeField``.
  491. Usage example::
  492. >>> from datetime import date, datetime
  493. >>> from django.db.models import Count
  494. >>> from django.db.models.functions import (
  495. ... TruncDate, TruncDay, TruncHour, TruncMinute, TruncSecond,
  496. ... )
  497. >>> from django.utils import timezone
  498. >>> import pytz
  499. >>> start1 = datetime(2014, 6, 15, 14, 30, 50, 321, tzinfo=timezone.utc)
  500. >>> Experiment.objects.create(start_time=start1, start_date=start1.date())
  501. >>> melb = pytz.timezone('Australia/Melbourne')
  502. >>> Experiment.objects.annotate(
  503. ... date=TruncDate('start_time'),
  504. ... day=TruncDay('start_time', tzinfo=melb),
  505. ... hour=TruncHour('start_time', tzinfo=melb),
  506. ... minute=TruncMinute('start_time'),
  507. ... second=TruncSecond('start_time'),
  508. ... ).values('date', 'day', 'hour', 'minute', 'second').get()
  509. {'date': datetime.date(2014, 6, 15),
  510. 'day': datetime.datetime(2014, 6, 16, 0, 0, tzinfo=<DstTzInfo 'Australia/Melbourne' AEST+10:00:00 STD>),
  511. 'hour': datetime.datetime(2014, 6, 16, 0, 0, tzinfo=<DstTzInfo 'Australia/Melbourne' AEST+10:00:00 STD>),
  512. 'minute': 'minute': datetime.datetime(2014, 6, 15, 14, 30, tzinfo=<UTC>),
  513. 'second': datetime.datetime(2014, 6, 15, 14, 30, 50, tzinfo=<UTC>)
  514. }