mirror of
				https://github.com/django/django.git
				synced 2025-10-26 07:06:08 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			670 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			670 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
| PostgreSQL specific model fields
 | |
| ================================
 | |
| 
 | |
| All of these fields are available from the ``django.contrib.postgres.fields``
 | |
| module.
 | |
| 
 | |
| .. currentmodule:: django.contrib.postgres.fields
 | |
| 
 | |
| ArrayField
 | |
| ----------
 | |
| 
 | |
| .. class:: ArrayField(base_field, size=None, **options)
 | |
| 
 | |
|     A field for storing lists of data. Most field types can be used, you simply
 | |
|     pass another field instance as the :attr:`base_field
 | |
|     <ArrayField.base_field>`. You may also specify a :attr:`size
 | |
|     <ArrayField.size>`. ``ArrayField`` can be nested to store multi-dimensional
 | |
|     arrays.
 | |
| 
 | |
|     .. attribute:: base_field
 | |
| 
 | |
|         This is a required argument.
 | |
| 
 | |
|         Specifies the underlying data type and behavior for the array. It
 | |
|         should be an instance of a subclass of
 | |
|         :class:`~django.db.models.Field`. For example, it could be an
 | |
|         :class:`~django.db.models.IntegerField` or a
 | |
|         :class:`~django.db.models.CharField`. Most field types are permitted,
 | |
|         with the exception of those handling relational data
 | |
|         (:class:`~django.db.models.ForeignKey`,
 | |
|         :class:`~django.db.models.OneToOneField` and
 | |
|         :class:`~django.db.models.ManyToManyField`).
 | |
| 
 | |
|         It is possible to nest array fields - you can specify an instance of
 | |
|         ``ArrayField`` as the ``base_field``. For example::
 | |
| 
 | |
|             from django.db import models
 | |
|             from django.contrib.postgres.fields import ArrayField
 | |
| 
 | |
|             class ChessBoard(models.Model):
 | |
|                 board = ArrayField(
 | |
|                     ArrayField(
 | |
|                         models.CharField(max_length=10, blank=True),
 | |
|                         size=8,
 | |
|                     ),
 | |
|                     size=8,
 | |
|                 )
 | |
| 
 | |
|         Transformation of values between the database and the model, validation
 | |
|         of data and configuration, and serialization are all delegated to the
 | |
|         underlying base field.
 | |
| 
 | |
|     .. attribute:: size
 | |
| 
 | |
|         This is an optional argument.
 | |
| 
 | |
|         If passed, the array will have a maximum size as specified. This will
 | |
|         be passed to the database, although PostgreSQL at present does not
 | |
|         enforce the restriction.
 | |
| 
 | |
| .. note::
 | |
| 
 | |
|     When nesting ``ArrayField``, whether you use the `size` parameter or not,
 | |
|     PostgreSQL requires that the arrays are rectangular::
 | |
| 
 | |
|         from django.contrib.postgres.fields import ArrayField
 | |
|         from django.db import models
 | |
| 
 | |
|         class Board(models.Model):
 | |
|             pieces = ArrayField(ArrayField(models.IntegerField()))
 | |
| 
 | |
|         # Valid
 | |
|         Board(pieces=[
 | |
|             [2, 3],
 | |
|             [2, 1],
 | |
|         ])
 | |
| 
 | |
|         # Not valid
 | |
|         Board(pieces=[
 | |
|             [2, 3],
 | |
|             [2],
 | |
|         ])
 | |
| 
 | |
|     If irregular shapes are required, then the underlying field should be made
 | |
|     nullable and the values padded with ``None``.
 | |
| 
 | |
| Querying ArrayField
 | |
| ^^^^^^^^^^^^^^^^^^^
 | |
| 
 | |
| There are a number of custom lookups and transforms for :class:`ArrayField`.
 | |
| We will use the following example model::
 | |
| 
 | |
|     from django.db import models
 | |
|     from django.contrib.postgres.fields import ArrayField
 | |
| 
 | |
|     class Post(models.Model):
 | |
|         name = models.CharField(max_length=200)
 | |
|         tags = ArrayField(models.CharField(max_length=200), blank=True)
 | |
| 
 | |
|         def __str__(self):  # __unicode__ on Python 2
 | |
|             return self.name
 | |
| 
 | |
| .. fieldlookup:: arrayfield.contains
 | |
| 
 | |
| contains
 | |
| ~~~~~~~~
 | |
| 
 | |
| The :lookup:`contains` lookup is overridden on :class:`ArrayField`. The
 | |
| returned objects will be those where the values passed are a subset of the
 | |
| data. It uses the SQL operator ``@>``. For example::
 | |
| 
 | |
|     >>> Post.objects.create(name='First post', tags=['thoughts', 'django'])
 | |
|     >>> Post.objects.create(name='Second post', tags=['thoughts'])
 | |
|     >>> Post.objects.create(name='Third post', tags=['tutorial', 'django'])
 | |
| 
 | |
|     >>> Post.objects.filter(tags__contains=['thoughts'])
 | |
|     [<Post: First post>, <Post: Second post>]
 | |
| 
 | |
|     >>> Post.objects.filter(tags__contains=['django'])
 | |
|     [<Post: First post>, <Post: Third post>]
 | |
| 
 | |
|     >>> Post.objects.filter(tags__contains=['django', 'thoughts'])
 | |
|     [<Post: First post>]
 | |
| 
 | |
| .. fieldlookup:: arrayfield.contained_by
 | |
| 
 | |
| contained_by
 | |
| ~~~~~~~~~~~~
 | |
| 
 | |
| This is the inverse of the :lookup:`contains <arrayfield.contains>` lookup -
 | |
| the objects returned will be those where the data is a subset of the values
 | |
| passed. It uses the SQL operator ``<@``. For example::
 | |
| 
 | |
|     >>> Post.objects.create(name='First post', tags=['thoughts', 'django'])
 | |
|     >>> Post.objects.create(name='Second post', tags=['thoughts'])
 | |
|     >>> Post.objects.create(name='Third post', tags=['tutorial', 'django'])
 | |
| 
 | |
|     >>> Post.objects.filter(tags__contained_by=['thoughts', 'django'])
 | |
|     [<Post: First post>, <Post: Second post>]
 | |
| 
 | |
|     >>> Post.objects.filter(tags__contained_by=['thoughts', 'django', 'tutorial'])
 | |
|     [<Post: First post>, <Post: Second post>, <Post: Third post>]
 | |
| 
 | |
| .. fieldlookup:: arrayfield.overlap
 | |
| 
 | |
| overlap
 | |
| ~~~~~~~
 | |
| 
 | |
| Returns objects where the data shares any results with the values passed. Uses
 | |
| the SQL operator ``&&``. For example::
 | |
| 
 | |
|     >>> Post.objects.create(name='First post', tags=['thoughts', 'django'])
 | |
|     >>> Post.objects.create(name='Second post', tags=['thoughts'])
 | |
|     >>> Post.objects.create(name='Third post', tags=['tutorial', 'django'])
 | |
| 
 | |
|     >>> Post.objects.filter(tags__overlap=['thoughts'])
 | |
|     [<Post: First post>, <Post: Second post>]
 | |
| 
 | |
|     >>> Post.objects.filter(tags__overlap=['thoughts', 'tutorial'])
 | |
|     [<Post: First post>, <Post: Second post>, <Post: Third post>]
 | |
| 
 | |
| .. fieldlookup:: arrayfield.len
 | |
| 
 | |
| len
 | |
| ~~~
 | |
| 
 | |
| Returns the length of the array. The lookups available afterwards are those
 | |
| available for :class:`~django.db.models.IntegerField`. For example::
 | |
| 
 | |
|     >>> Post.objects.create(name='First post', tags=['thoughts', 'django'])
 | |
|     >>> Post.objects.create(name='Second post', tags=['thoughts'])
 | |
| 
 | |
|     >>> Post.objects.filter(tags__len=1)
 | |
|     [<Post: Second post>]
 | |
| 
 | |
| .. fieldlookup:: arrayfield.index
 | |
| 
 | |
| Index transforms
 | |
| ~~~~~~~~~~~~~~~~
 | |
| 
 | |
| This class of transforms allows you to index into the array in queries. Any
 | |
| non-negative integer can be used. There are no errors if it exceeds the
 | |
| :attr:`size <ArrayField.size>` of the array. The lookups available after the
 | |
| transform are those from the :attr:`base_field <ArrayField.base_field>`. For
 | |
| example::
 | |
| 
 | |
|     >>> Post.objects.create(name='First post', tags=['thoughts', 'django'])
 | |
|     >>> Post.objects.create(name='Second post', tags=['thoughts'])
 | |
| 
 | |
|     >>> Post.objects.filter(tags__0='thoughts')
 | |
|     [<Post: First post>, <Post: Second post>]
 | |
| 
 | |
|     >>> Post.objects.filter(tags__1__iexact='Django')
 | |
|     [<Post: First post>]
 | |
| 
 | |
|     >>> Post.objects.filter(tags__276='javascript')
 | |
|     []
 | |
| 
 | |
| .. note::
 | |
| 
 | |
|     PostgreSQL uses 1-based indexing for array fields when writing raw SQL.
 | |
|     However these indexes and those used in :lookup:`slices <arrayfield.slice>`
 | |
|     use 0-based indexing to be consistent with Python.
 | |
| 
 | |
| .. fieldlookup:: arrayfield.slice
 | |
| 
 | |
| Slice transforms
 | |
| ~~~~~~~~~~~~~~~~
 | |
| 
 | |
| This class of transforms allow you to take a slice of the array. Any two
 | |
| non-negative integers can be used, separated by a single underscore. The
 | |
| lookups available after the transform do not change. For example::
 | |
| 
 | |
|     >>> Post.objects.create(name='First post', tags=['thoughts', 'django'])
 | |
|     >>> Post.objects.create(name='Second post', tags=['thoughts'])
 | |
|     >>> Post.objects.create(name='Third post', tags=['django', 'python', 'thoughts'])
 | |
| 
 | |
|     >>> Post.objects.filter(tags__0_1=['thoughts'])
 | |
|     [<Post: First post>]
 | |
| 
 | |
|     >>> Post.objects.filter(tags__0_2__contains='thoughts')
 | |
|     [<Post: First post>, <Post: Second post>]
 | |
| 
 | |
| .. note::
 | |
| 
 | |
|     PostgreSQL uses 1-based indexing for array fields when writing raw SQL.
 | |
|     However these slices and those used in :lookup:`indexes <arrayfield.index>`
 | |
|     use 0-based indexing to be consistent with Python.
 | |
| 
 | |
| .. admonition:: Multidimensional arrays with indexes and slices
 | |
| 
 | |
|     PostgreSQL has some rather esoteric behavior when using indexes and slices
 | |
|     on multidimensional arrays. It will always work to use indexes to reach
 | |
|     down to the final underlying data, but most other slices behave strangely
 | |
|     at the database level and cannot be supported in a logical, consistent
 | |
|     fashion by Django.
 | |
| 
 | |
| Indexing ArrayField
 | |
| ^^^^^^^^^^^^^^^^^^^
 | |
| 
 | |
| At present using :attr:`~django.db.models.Field.db_index` will create a
 | |
| ``btree`` index. This does not offer particularly significant help to querying.
 | |
| A more useful index is a ``GIN`` index, which you should create using a
 | |
| :class:`~django.db.migrations.operations.RunSQL` operation.
 | |
| 
 | |
| HStoreField
 | |
| -----------
 | |
| 
 | |
| .. class:: HStoreField(**options)
 | |
| 
 | |
|     A field for storing mappings of strings to strings. The Python data type
 | |
|     used is a ``dict``.
 | |
| 
 | |
| .. note::
 | |
| 
 | |
|     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`.
 | |
| 
 | |
| Querying HStoreField
 | |
| ^^^^^^^^^^^^^^^^^^^^
 | |
| 
 | |
| In addition to the ability to query by key, there are a number of custom
 | |
| lookups available for ``HStoreField``.
 | |
| 
 | |
| We will use the following example model::
 | |
| 
 | |
|     from django.contrib.postgres.fields import HStoreField
 | |
|     from django.db import models
 | |
| 
 | |
|     class Dog(models.Model):
 | |
|         name = models.CharField(max_length=200)
 | |
|         data = HStoreField()
 | |
| 
 | |
|         def __str__(self):  # __unicode__ on Python 2
 | |
|             return self.name
 | |
| 
 | |
| .. fieldlookup:: hstorefield.key
 | |
| 
 | |
| Key lookups
 | |
| ~~~~~~~~~~~
 | |
| 
 | |
| To query based on a given key, you simply use that key as the lookup name::
 | |
| 
 | |
|     >>> Dog.objects.create(name='Rufus', data={'breed': 'labrador'})
 | |
|     >>> Dog.objects.create(name='Meg', data={'breed': 'collie'})
 | |
| 
 | |
|     >>> Dog.objects.filter(data__breed='collie')
 | |
|     [<Dog: Meg>]
 | |
| 
 | |
| You can chain other lookups after key lookups::
 | |
| 
 | |
|     >>> Dog.objects.filter(data__breed__contains='l')
 | |
|     [<Dog: Rufus>, <Dog: Meg>]
 | |
| 
 | |
| If the key you wish to query by clashes with the name of another lookup, you
 | |
| need to use the :lookup:`hstorefield.contains` lookup instead.
 | |
| 
 | |
| .. warning::
 | |
| 
 | |
|     Since any string could be a key in a hstore value, any lookup other than
 | |
|     those listed below will be interpreted as a key lookup. No errors are
 | |
|     raised. Be extra careful for typing mistakes, and always check your queries
 | |
|     work as you intend.
 | |
| 
 | |
| .. fieldlookup:: hstorefield.contains
 | |
| 
 | |
| contains
 | |
| ~~~~~~~~
 | |
| 
 | |
| The :lookup:`contains` lookup is overridden on
 | |
| :class:`~django.contrib.postgres.fields.HStoreField`. The returned objects are
 | |
| those where the given ``dict`` of key-value pairs are all contained in the
 | |
| field. It uses the SQL operator ``@>``. For example::
 | |
| 
 | |
|     >>> Dog.objects.create(name='Rufus', data={'breed': 'labrador', 'owner': 'Bob'})
 | |
|     >>> Dog.objects.create(name='Meg', data={'breed': 'collie', 'owner': 'Bob'})
 | |
|     >>> Dog.objects.create(name='Fred', data={})
 | |
| 
 | |
|     >>> Dog.objects.filter(data__contains={'owner': 'Bob'})
 | |
|     [<Dog: Rufus>, <Dog: Meg>]
 | |
| 
 | |
|     >>> Dog.objects.filter(data__contains={'breed': 'collie'})
 | |
|     [<Dog: Meg>]
 | |
| 
 | |
| .. fieldlookup:: hstorefield.contained_by
 | |
| 
 | |
| contained_by
 | |
| ~~~~~~~~~~~~
 | |
| 
 | |
| This is the inverse of the :lookup:`contains <hstorefield.contains>` lookup -
 | |
| the objects returned will be those where the key-value pairs on the object are
 | |
| a subset of those in the value passed. It uses the SQL operator ``<@``. For
 | |
| example::
 | |
| 
 | |
|     >>> Dog.objects.create(name='Rufus', data={'breed': 'labrador', 'owner': 'Bob'})
 | |
|     >>> Dog.objects.create(name='Meg', data={'breed': 'collie', 'owner': 'Bob'})
 | |
|     >>> Dog.objects.create(name='Fred', data={})
 | |
| 
 | |
|     >>> Dog.objects.filter(data__contained_by={'breed': 'collie', 'owner': 'Bob'})
 | |
|     [<Dog: Meg>, <Dog: Fred>]
 | |
| 
 | |
|     >>> Dog.objects.filter(data__contained_by={'breed': 'collie'})
 | |
|     [<Dog: Fred>]
 | |
| 
 | |
| .. fieldlookup:: hstorefield.has_key
 | |
| 
 | |
| has_key
 | |
| ~~~~~~~
 | |
| 
 | |
| Returns objects where the given key is in the data. Uses the SQL operator
 | |
| ``?``. For example::
 | |
| 
 | |
|     >>> Dog.objects.create(name='Rufus', data={'breed': 'labrador'})
 | |
|     >>> Dog.objects.create(name='Meg', data={'breed': 'collie', 'owner': 'Bob'})
 | |
| 
 | |
|     >>> Dog.objects.filter(data__has_key='owner')
 | |
|     [<Dog: Meg>]
 | |
| 
 | |
| .. fieldlookup:: hstorefield.has_keys
 | |
| 
 | |
| has_keys
 | |
| ~~~~~~~~
 | |
| 
 | |
| Returns objects where all of the given keys are in the data. Uses the SQL operator
 | |
| ``?&``. For example::
 | |
| 
 | |
|     >>> Dog.objects.create(name='Rufus', data={})
 | |
|     >>> Dog.objects.create(name='Meg', data={'breed': 'collie', 'owner': 'Bob'})
 | |
| 
 | |
|     >>> Dog.objects.filter(data__has_keys=['breed', 'owner'])
 | |
|     [<Dog: Meg>]
 | |
| 
 | |
| .. fieldlookup:: hstorefield.keys
 | |
| 
 | |
| keys
 | |
| ~~~~
 | |
| 
 | |
| Returns objects where the array of keys is the given value. Note that the order
 | |
| is not guaranteed to be reliable, so this transform is mainly useful for using
 | |
| in conjunction with lookups on
 | |
| :class:`~django.contrib.postgres.fields.ArrayField`. Uses the SQL function
 | |
| ``akeys()``. For example::
 | |
| 
 | |
|     >>> Dog.objects.create(name='Rufus', data={'toy': 'bone'})
 | |
|     >>> Dog.objects.create(name='Meg', data={'breed': 'collie', 'owner': 'Bob'})
 | |
| 
 | |
|     >>> Dog.objects.filter(data__keys__overlap=['breed', 'toy'])
 | |
|     [<Dog: Rufus>, <Dog: Meg>]
 | |
| 
 | |
| .. fieldlookup:: hstorefield.values
 | |
| 
 | |
| values
 | |
| ~~~~~~
 | |
| 
 | |
| Returns objects where the array of values is the given value. Note that the
 | |
| order is not guaranteed to be reliable, so this transform is mainly useful for
 | |
| using in conjunction with lookups on
 | |
| :class:`~django.contrib.postgres.fields.ArrayField`. Uses the SQL function
 | |
| ``avalues()``. For example::
 | |
| 
 | |
|     >>> Dog.objects.create(name='Rufus', data={'breed': 'labrador'})
 | |
|     >>> Dog.objects.create(name='Meg', data={'breed': 'collie', 'owner': 'Bob'})
 | |
| 
 | |
|     >>> 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 subclass 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.
 |