所有这些字段都可以从django.contrib.postgres.fields模块获取。
用于存储数据列表的字段。可以使用大多数字段类型,只需将另一个字段实例传递为base_field。您也可以指定size。ArrayField可以嵌套存储多维数组。
这是必需的参数。
指定数组的底层数据类型和行为。它应该是Field的子类的实例。例如,它可以是IntegerField或CharField。除了处理关系数据(ForeignKey,OneToOneField和ManyToManyField)的字段类型,允许使用大多数字段类型。
可以嵌套数组字段 - 可以将ArrayField的实例指定为base_field。例如:
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,
)
数据库和模型之间的值转换,数据和配置的验证以及序列化都被委派给底层基本字段。
这是一个可选参数。
如果传递,数组将具有指定的最大大小。这将被传递到数据库,虽然PostgreSQL目前没有强制实施限制。
注意
当嵌套ArrayField时,无论您是否使用size参数,PostgreSQL都要求数组为矩形:
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],
])
如果需要不规则形状,则应将基础字段设为可空,并用None填充值。
对于ArrayField,有一些自定义查找和变换。我们将使用以下示例模型:
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
contains查找在ArrayField上覆盖。返回的对象将是传递的值是数据的子集的那些对象。它使用SQL运算符@>。例如:
>>> 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>]
这是contains查找的逆 - 返回的对象将是那些数据是传递的值的子集的对象。它使用SQL运算符<@。例如:
>>> 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>]
返回数据与传递的值共享任何结果的对象。使用SQL运算符&&。例如:
>>> 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>]
返回数组的长度。稍后可用的查找是可用于IntegerField的查找。例如:
>>> 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>]
这类变换允许您在查询中索引到数组。可以使用任何非负整数。如果超过数组的size,则没有错误。变换后可用的查找是来自base_field的查找。例如:
>>> 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')
[]
注意
在编写原始SQL时,PostgreSQL对数组字段使用基于1的索引。但是,这些索引和slices使用基于0的索引与Python一致。
这类变换允许你取一个数组的切片。可以使用任何两个非负整数,由单个下划线分隔。转换后可用的查找不会更改。例如:
>>> 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>]
注意
在编写原始SQL时,PostgreSQL对数组字段使用基于1的索引。然而,这些切片和indexes使用基于0的索引来与Python一致。
具有索引和切片的多维数组
当在多维数组上使用索引和切片时,PostgreSQL有一些相当深奥的行为。它将始终使用索引来达到最终的底层数据,但大多数其他切片在数据库级别上表现奇怪,不能以Django的逻辑一致方式支持。
用于存储字符串到字符串的映射的字段。使用的Python数据类型是dict。
要使用此字段,您需要:
You’ll see an error like can't adapt type 'dict' if you skip the first step, or type "hstore" does not exist if you skip the second.
注意
在某些情况下,可能需要或限制对给定字段有效的键。这可以使用KeysValidator来完成。
除了通过键查询的功能之外,还有一些可用于HStoreField的自定义查找。
我们将使用以下示例模型:
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
要基于给定的键进行查询,只需使用该键作为查找名称:
>>> Dog.objects.create(name='Rufus', data={'breed': 'labrador'})
>>> Dog.objects.create(name='Meg', data={'breed': 'collie'})
>>> Dog.objects.filter(data__breed='collie')
[<Dog: Meg>]
您可以在键查找后链接其他查找:
>>> Dog.objects.filter(data__breed__contains='l')
[<Dog: Rufus>, <Dog: Meg>]
如果您希望查询的键与另一个查找的名称冲突,则需要使用hstorefield.contains查找。
警告
因为任何字符串都可能是hstore值中的键,除了下面列出的以外的任何查找都将被解释为键查找。不会产生错误。请特别小心输入错误,并始终检查您的查询工作,因为你打算。
在HStoreField上覆盖contains查找。返回的对象是那些给定的dict键值对都包含在字段中的对象。它使用SQL运算符@>。例如:
>>> 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>]
这是contains查找的逆 - 返回的对象将是对象上的键值对是传递的值的子集的对象。它使用SQL运算符<@。例如:
>>> 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>]
返回给定键在数据中的对象。使用SQL运算符?。例如:
>>> 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>]
返回所有给定键在数据中的对象。使用SQL运算符?&。例如:
>>> 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>]
返回其中键的数组为给定值的对象。请注意,顺序不能保证可靠,因此此变换主要用于与ArrayField上的查找结合使用。使用SQL函数akeys()。例如:
>>> 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>]
返回值的数组为给定值的对象。请注意,顺序不能保证可靠,因此此变换主要用于与ArrayField上的查找结合使用。使用SQL函数avalues()。例如:
>>> 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>]
有五个范围字段类型,对应于PostgreSQL中的内置范围类型。这些字段用于存储值的范围;例如事件的开始和结束时间戳,或活动适合的年龄范围。
所有范围字段都转换为python中的psycopg2 Range objects,但如果不需要边界信息,也接受元组作为输入。默认值为下限,上限为排除。
存储整数范围。基于IntegerField。由数据库中的int4range和Python中的NumericRange表示。
存储大整数的范围。基于BigIntegerField。由数据库中的int8range和Python中的NumericRange表示。
存储浮点值的范围。基于FloatField。在数据库中由numrange表示,在Python中由NumericRange表示。
存储时间戳范围。基于DateTimeField。在数据库中由tztsrange表示,在Python中由DateTimeTZRange表示。
对于范围字段,有许多自定义查找和变换。它们可用于所有上述字段,但我们将使用以下示例模型:
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
我们还将使用以下示例对象:
>>> Event.objects.create(name='Soft play', ages=(0, 10))
>>> Event.objects.create(name='Pub trip', ages=(21, None))
和NumericRange:
>>> from psycopg2.extras import NumericRange
As with other PostgreSQL fields, there are three standard containment operators: contains, contained_by and overlap, using the SQL operators @>, <@, and && respectively.
>>> Event.objects.filter(ages__contains=NumericRange(4, 5))
[<Event: Soft play>]
>>> Event.objects.filter(ages__contained_by=NumericRange(0, 15))
[<Event: Soft play>]
>>> Event.objects.filter(ages__overlap=NumericRange(8, 12))
[<Event: Soft play>]
范围字段支持标准查找:lt,gt,lte和gte。这些不是特别有帮助 - 它们首先比较下限,然后仅在必要时比较上限。这也是用于按范围字段排序的策略。最好使用特定的范围比较运算符。
返回的范围严格小于通过的范围。换句话说,返回范围中的所有点都小于通过范围中的所有点。
>>> Event.objects.filter(ages__fully_lt=NumericRange(11, 15))
[<Event: Soft play>]
返回的范围严格大于传递的范围。换句话说,返回范围中的所有点都大于通过范围中的所有点。
>>> Event.objects.filter(ages__fully_gt=NumericRange(11, 15))
[<Event: Pub trip>]
返回的范围不包含小于传递范围的任何点,也就是说返回范围的下限至少是传递范围的下限。
>>> Event.objects.filter(ages__not_lt=NumericRange(0, 15))
[<Event: Soft play>, <Event: Pub trip>]
返回的范围不包含大于传递范围的任何点,即返回范围的上限最多为传递范围的上限。
>>> Event.objects.filter(ages__not_gt=NumericRange(3, 10))
[<Event: Soft play>]
返回的范围与传递的范围共享绑定。
>>> Event.objects.filter(ages__adjacent_to=NumericRange(10, 21))
[<Event: Soft play>, <Event: Pub trip>]
有三个变换可用于查询。您可以提取下限或上限,或基于空的查询。
返回的对象具有给定的下限。可以链接到基本字段的有效查找。
>>> Event.objects.filter(ages__startswith=21)
[<Event: Pub trip>]
返回的对象具有给定的上限。可以链接到基本字段的有效查找。
>>> Event.objects.filter(ages__endswith=10)
[<Event: Soft play>]
PostgreSQL允许定义自定义范围类型。Django的模型和表单字段实现使用下面的基类,psycopg2提供了一个register_range()以允许使用自定义范围类型。
模型范围字段的基类。
要使用的模型字段。
要使用的psycopg2范围类型。
要使用的表单字段类。应为django.contrib.postgres.forms.BaseRangeField的子类。
2015年5月13日