mirror of
https://github.com/django/django.git
synced 2025-08-04 02:48:35 +00:00
Added HStoreField.
Thanks to `django-hstore` for inspiration in some areas, and many people for reviews.
This commit is contained in:
parent
5c517ec218
commit
36f514f065
22 changed files with 864 additions and 6 deletions
|
@ -61,8 +61,8 @@ ArrayField
|
|||
When nesting ``ArrayField``, whether you use the `size` parameter or not,
|
||||
PostgreSQL requires that the arrays are rectangular::
|
||||
|
||||
from django.db import models
|
||||
from django.contrib.postgres.fields import ArrayField
|
||||
from django.db import models
|
||||
|
||||
class Board(models.Model):
|
||||
pieces = ArrayField(ArrayField(models.IntegerField()))
|
||||
|
@ -95,7 +95,7 @@ We will use the following example model::
|
|||
name = models.CharField(max_length=200)
|
||||
tags = ArrayField(models.CharField(max_length=200), blank=True)
|
||||
|
||||
def __str__(self): # __unicode__ on python 2
|
||||
def __str__(self): # __unicode__ on Python 2
|
||||
return self.name
|
||||
|
||||
.. fieldlookup:: arrayfield.contains
|
||||
|
@ -240,3 +240,165 @@ 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>]
|
||||
|
|
|
@ -133,3 +133,23 @@ SplitArrayField
|
|||
['1', '2', ''] # -> [1, 2]
|
||||
['1', '', '3'] # -> [1, None, 3]
|
||||
['', '2', ''] # -> [None, 2]
|
||||
|
||||
HStoreField
|
||||
-----------
|
||||
|
||||
.. class:: HStoreField
|
||||
|
||||
A field which accepts JSON encoded data for an
|
||||
:class:`~django.contrib.postgres.fields.HStoreField`. It will cast all the
|
||||
values to strings. It is represented by an HTML ``<textarea>``.
|
||||
|
||||
.. admonition:: User friendly forms
|
||||
|
||||
``HStoreField`` is not particularly user friendly in most cases,
|
||||
however it is a useful way to format data from a client-side widget for
|
||||
submission to the server.
|
||||
|
||||
.. 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`.
|
||||
|
|
|
@ -26,3 +26,5 @@ a number of PostgreSQL specific data types.
|
|||
|
||||
fields
|
||||
forms
|
||||
operations
|
||||
validators
|
||||
|
|
27
docs/ref/contrib/postgres/operations.txt
Normal file
27
docs/ref/contrib/postgres/operations.txt
Normal file
|
@ -0,0 +1,27 @@
|
|||
Database migration operations
|
||||
=============================
|
||||
|
||||
All of these :doc:`operations </ref/migration-operations>` are available from
|
||||
the ``django.contrib.postgres.operations`` module.
|
||||
|
||||
.. currentmodule:: django.contrib.postgres.operations
|
||||
|
||||
CreateExtension
|
||||
---------------
|
||||
|
||||
.. class:: CreateExtension(name)
|
||||
|
||||
An ``Operation`` subclass which installs PostgreSQL extensions.
|
||||
|
||||
.. attribute:: name
|
||||
|
||||
This is a required argument. The name of the extension to be installed.
|
||||
|
||||
HStoreExtension
|
||||
---------------
|
||||
|
||||
.. class:: HStoreExtension()
|
||||
|
||||
A subclass of :class:`~django.contrib.postgres.operations.CreateExtension`
|
||||
which will install the ``hstore`` extension and also immediately set up the
|
||||
connection to interpret hstore data.
|
20
docs/ref/contrib/postgres/validators.txt
Normal file
20
docs/ref/contrib/postgres/validators.txt
Normal file
|
@ -0,0 +1,20 @@
|
|||
==========
|
||||
Validators
|
||||
==========
|
||||
|
||||
.. module:: django.contrib.postgres.validators
|
||||
|
||||
``KeysValidator``
|
||||
-----------------
|
||||
|
||||
.. class:: KeysValidator(keys, strict=False, messages=None)
|
||||
|
||||
Validates that the given keys are contained in the value. If ``strict`` is
|
||||
``True``, then it also checks that there are no other keys present.
|
||||
|
||||
The ``messages`` passed should be a dict containing the keys
|
||||
``missing_keys`` and/or ``extra_keys``.
|
||||
|
||||
.. note::
|
||||
Note that this checks only for the existence of a given key, not that
|
||||
the value of a key is non-empty.
|
Loading…
Add table
Add a link
Reference in a new issue