diff options
| author | Marc Tamlyn <marc.tamlyn@gmail.com> | 2015-01-10 16:14:20 +0000 |
|---|---|---|
| committer | Marc Tamlyn <marc.tamlyn@gmail.com> | 2015-01-10 16:18:19 +0000 |
| commit | 48ad288679a0cb2e2cfb17f128903e6c5b1c4870 (patch) | |
| tree | 75bacb810dbe071058b5c5cf7d8dcb8e20f3f500 /docs | |
| parent | 916e38802f151b34aaca487dc7e928946e81be73 (diff) | |
Fixed #24001 -- Added range fields for PostgreSQL.
Added support for PostgreSQL range types to contrib.postgres.
- 5 new model fields
- 4 new form fields
- New validators
- Uses psycopg2's range type implementation in python
Diffstat (limited to 'docs')
| -rw-r--r-- | docs/conf.py | 1 | ||||
| -rw-r--r-- | docs/ref/contrib/postgres/fields.txt | 263 | ||||
| -rw-r--r-- | docs/ref/contrib/postgres/forms.txt | 45 | ||||
| -rw-r--r-- | docs/ref/contrib/postgres/validators.txt | 13 | ||||
| -rw-r--r-- | docs/releases/1.8.txt | 6 | ||||
| -rw-r--r-- | docs/spelling_wordlist | 1 |
6 files changed, 326 insertions, 3 deletions
diff --git a/docs/conf.py b/docs/conf.py index e9063f3200..68b0389c51 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -130,6 +130,7 @@ intersphinx_mapping = { 'sphinx': ('http://sphinx-doc.org/', None), 'six': ('http://pythonhosted.org/six/', None), 'formtools': ('http://django-formtools.readthedocs.org/en/latest/', None), + 'psycopg2': ('http://initd.org/psycopg/docs/', None), } # Python's docs don't change every week. diff --git a/docs/ref/contrib/postgres/fields.txt b/docs/ref/contrib/postgres/fields.txt index 1cdd21a59b..f4fae93da0 100644 --- a/docs/ref/contrib/postgres/fields.txt +++ b/docs/ref/contrib/postgres/fields.txt @@ -402,3 +402,266 @@ using in conjunction with lookups on >>> Dog.objects.filter(data__values__contains=['collie']) [<Dog: Meg>] + +.. _range-fields: + +Range Fields +------------ + +There are five range field types, corresponding to the built-in range types in +PostgreSQL. These fields are used to store a range of values; for example the +start and end timestamps of an event, or the range of ages an activity is +suitable for. + +All of the range fields translate to :ref:`psycopg2 Range objects +<psycopg2:adapt-range>` in python, but also accept tuples as input if no bounds +information is necessary. The default is lower bound included, upper bound +excluded. + +IntegerRangeField +^^^^^^^^^^^^^^^^^ + +.. class:: IntegerRangeField(**options) + + Stores a range of integers. Based on an + :class:`~django.db.models.IntegerField`. Represented by an ``int4range`` in + the database and a :class:`~psycopg2:psycopg2.extras.NumericRange` in + Python. + +BigIntegerRangeField +^^^^^^^^^^^^^^^^^^^^ + +.. class:: BigIntegerRangeField(**options) + + Stores a range of large integers. Based on a + :class:`~django.db.models.BigIntegerField`. Represented by an ``int8range`` + in the database and a :class:`~psycopg2:psycopg2.extras.NumericRange` in + Python. + +FloatRangeField +^^^^^^^^^^^^^^^ + +.. class:: FloatRangeField(**options) + + Stores a range of floating point values. Based on a + :class:`~django.db.models.FloatField`. Represented by a ``numrange`` in the + database and a :class:`~psycopg2:psycopg2.extras.NumericRange` in Python. + +DateTimeRangeField +^^^^^^^^^^^^^^^^^^ + +.. class:: DateTimeRangeField(**options) + + Stores a range of timestamps. Based on a + :class:`~django.db.models.DateTimeField`. Represented by a ``tztsrange`` in + the database and a :class:`~psycopg2:psycopg2.extras.DateTimeTZRange` in + Python. + +DateRangeField +^^^^^^^^^^^^^^ + +.. class:: DateRangeField(**options) + + Stores a range of dates. Based on a + :class:`~django.db.models.DateField`. Represented by a ``daterange`` in the + database and a :class:`~psycopg2:psycopg2.extras.DateRange` in Python. + +Querying Range Fields +^^^^^^^^^^^^^^^^^^^^^ + +There are a number of custom lookups and transforms for range fields. They are +available on all the above fields, but we will use the following example +model:: + + from django.contrib.postgres.fields import IntegerRangeField + from django.db import models + + class Event(models.Model): + name = models.CharField(max_length=200) + ages = IntegerRangeField() + + def __str__(self): # __unicode__ on Python 2 + return self.name + +We will also use the following example objects:: + + >>> Event.objects.create(name='Soft play', ages=(0, 10)) + >>> Event.objects.create(name='Pub trip', ages=(21, None)) + +and ``NumericRange``: + + >>> from psycopg2.extras import NumericRange + +Containment functions +~~~~~~~~~~~~~~~~~~~~~ + +As with other PostgreSQL fields, there are three standard containment +operators: ``contains``, ``contained_by`` and ``overlap``, using the SQL +operators ``@>``, ``<@``, and ``&&`` respectively. + +.. fieldlookup:: rangefield.contains + +contains +'''''''' + + >>> Event.objects.filter(ages__contains=NumericRange(4, 5)) + [<Event: Soft play>] + +.. fieldlookup:: rangefield.contained_by + +contained_by +'''''''''''' + + >>> Event.objects.filter(ages__contained_by=NumericRange(0, 15)) + [<Event: Soft play>] + +.. fieldlookup:: rangefield.overlap + +overlap +''''''' + + >>> Event.objects.filter(ages__overlap=NumericRange(8, 12)) + [<Event: Soft play>] + +Comparison functions +~~~~~~~~~~~~~~~~~~~~ + +Range fields support the standard lookups: :lookup:`lt`, :lookup:`gt`, +:lookup:`lte` and :lookup:`gte`. These are not particularly helpful - they +compare the lower bounds first and then the upper bounds only if necessary. +This is also the strategy used to order by a range field. It is better to use +the specific range comparison operators. + +.. fieldlookup:: rangefield.fully_lt + +fully_lt +'''''''' + +The returned ranges are strictly less than the passed range. In other words, +all the points in the returned range are less than all those in the passed +range. + + >>> Event.objects.filter(ages__fully_lt=NumericRange(11, 15)) + [<Event: Soft play>] + +.. fieldlookup:: rangefield.fully_gt + +fully_gt +'''''''' + +The returned ranges are strictly greater than the passed range. In other words, +the all the points in the returned range are greater than all those in the +passed range. + + >>> Event.objects.filter(ages__fully_gt=NumericRange(11, 15)) + [<Event: Pub trip>] + +.. fieldlookup:: rangefield.not_lt + +not_lt +'''''' + +The returned ranges do not contain any points less than the passed range, that +is the lower bound of the returned range is at least the lower bound of the +passed range. + + >>> Event.objects.filter(ages__not_lt=NumericRange(0, 15)) + [<Event: Soft play>, <Event: Pub trip>] + +.. fieldlookup:: rangefield.not_gt + +not_gt +'''''' + +The returned ranges do not contain any points greater than the passed range, that +is the upper bound of the returned range is at most the upper bound of the +passed range. + + >>> Event.objects.filter(ages__not_gt=NumericRange(3, 10)) + [<Event: Soft play>] + +.. fieldlookup:: rangefield.adjacent_to + +adjacent_to +''''''''''' + +The returned ranges share a bound with the passed range. + + >>> Event.objects.filter(ages__adjacent_to=NumericRange(10, 21)) + [<Event: Soft play>, <Event: Pub trip>] + +Querying using the bounds +~~~~~~~~~~~~~~~~~~~~~~~~~ + +There are three transforms available for use in queries. You can extract the +lower or upper bound, or query based on emptiness. + +.. fieldlookup:: rangefield.startswith + +startswith +'''''''''' + +Returned objects have the given lower bound. Can be chained to valid lookups +for the base field. + + >>> Event.objects.filter(ages__startswith=21) + [<Event: Pub trip>] + +.. fieldlookup:: rangefield.endswith + +endswith +'''''''' + +Returned objects have the given upper bound. Can be chained to valid lookups +for the base field. + + >>> Event.objects.filter(ages__endswith=10) + [<Event: Soft play>] + +.. fieldlookup:: rangefield.isempty + +isempty +''''''' + +Returned objects are empty ranges. Can be chained to valid lookups for a +:class:`~django.db.models.BooleanField`. + + >>> Event.objects.filter(ages__isempty=True) + [] + +Defining your own range types +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +PostgreSQL allows the definition of custom range types. Django's model and form +field implementations use base classes below, and psycopg2 provides a +:func:`~psycopg2:psycopg2.extras.register_range` to allow use of custom range +types. + +.. class:: RangeField(**options) + + Base class for model range fields. + + .. attribute:: base_field + + The model field to use. + + .. attribute:: range_type + + The psycopg2 range type to use. + + .. attribute:: form_field + + The form field class to use. Should be a sublcass of + :class:`django.contrib.postgres.forms.BaseRangeField`. + +.. class:: django.contrib.postgres.forms.BaseRangeField + + Base class for form range fields. + + .. attribute:: base_field + + The form field to use. + + .. attribute:: range_type + + The psycopg2 range type to use. diff --git a/docs/ref/contrib/postgres/forms.txt b/docs/ref/contrib/postgres/forms.txt index fcf44ce6a5..f6226c4b55 100644 --- a/docs/ref/contrib/postgres/forms.txt +++ b/docs/ref/contrib/postgres/forms.txt @@ -154,3 +154,48 @@ HStoreField On occasions it may be useful to require or restrict the keys which are valid for a given field. This can be done using the :class:`~django.contrib.postgres.validators.KeysValidator`. + +Range Fields +------------ + +This group of fields all share similar functionality for accepting range data. +They are based on :class:`~django.forms.MultiValueField`. They treat one +omitted value as an unbounded range. They also validate that the lower bound is +not greater than the upper bound. + +IntegerRangeField +~~~~~~~~~~~~~~~~~ + +.. class:: IntegerRangeField + + Based on :class:`~django.forms.IntegerField` and translates its input into + :class:`~psycopg2:psycopg2.extras.NumericRange`. Default for + :class:`~django.contrib.postgres.fields.IntegerRangeField` and + :class:`~django.contrib.postgres.fields.BigIntegerRangeField`. + +FloatRangeField +~~~~~~~~~~~~~~~ + +.. class:: FloatRangeField + + Based on :class:`~django.forms.FloatField` and translates its input into + :class:`~psycopg2:psycopg2.extras.NumericRange`. Default for + :class:`~django.contrib.postgres.fields.FloatRangeField`. + +DateTimeRangeField +~~~~~~~~~~~~~~~~~~ + +.. class:: DateTimeRangeField + + Based on :class:`~django.forms.DateTimeField` and translates its input into + :class:`~psycopg2:psycopg2.extras.DateTimeTZRange`. Default for + :class:`~django.contrib.postgres.fields.DateTimeRangeField`. + +DateRangeField +~~~~~~~~~~~~~~ + +.. class:: DateRangeField + + Based on :class:`~django.forms.DateField` and translates its input into + :class:`~psycopg2:psycopg2.extras.DateRange`. Default for + :class:`~django.contrib.postgres.fields.DateRangeField`. diff --git a/docs/ref/contrib/postgres/validators.txt b/docs/ref/contrib/postgres/validators.txt index 76cd52510a..f35a40dd27 100644 --- a/docs/ref/contrib/postgres/validators.txt +++ b/docs/ref/contrib/postgres/validators.txt @@ -18,3 +18,16 @@ Validators .. note:: Note that this checks only for the existence of a given key, not that the value of a key is non-empty. + +Range validators +---------------- + +.. class:: RangeMaxValueValidator(limit_value, message=None) + + Validates that the upper bound of the range is not greater than + ``limit_value``. + +.. class:: RangeMinValueValidator(limit_value, message=None) + + Validates that the lower bound of the range is not less than the + ``limit_value``. diff --git a/docs/releases/1.8.txt b/docs/releases/1.8.txt index 64765fcea8..5372f0ae99 100644 --- a/docs/releases/1.8.txt +++ b/docs/releases/1.8.txt @@ -62,9 +62,9 @@ New PostgreSQL specific functionality Django now has a module with extensions for PostgreSQL specific features, such as :class:`~django.contrib.postgres.fields.ArrayField`, -:class:`~django.contrib.postgres.fields.HStoreField`, and :lookup:`unaccent` -lookup. A full breakdown of the features is available :doc:`in the -documentation </ref/contrib/postgres/index>`. +:class:`~django.contrib.postgres.fields.HStoreField`, :ref:`range-fields`, and +:lookup:`unaccent` lookup. A full breakdown of the features is available +:doc:`in the documentation </ref/contrib/postgres/index>`. New data types ~~~~~~~~~~~~~~ diff --git a/docs/spelling_wordlist b/docs/spelling_wordlist index 507e4f15c2..3d018703ed 100644 --- a/docs/spelling_wordlist +++ b/docs/spelling_wordlist @@ -309,6 +309,7 @@ irc iregex iriencode ise +isempty isnull iso istartswith |
