所有这些字段都可以从 django.contrib.postgres.fields 模块。
Index 和 Field.db_index 两者都创建B树索引,这在查询复杂数据类型时并没有特别有帮助。等指标 GinIndex 和 GistIndex 更适合,尽管索引选择取决于您正在使用的查询。一般来说,GiST可能是 range fields 和 HStoreField ,和杜松子酒可能对 ArrayField 。
ArrayField¶用于存储数据列表的字段。大多数字段类型都可以使用,并且您可以传递另一个字段实例作为 base_field .您还可以指定 size 。 ArrayField 可以嵌套以存储多维数组。
如果你给场 default 确保它是可调用的,例如 list (对于空默认值)或返回列表(如函数)的可调用项。使用不当 default=[] 创建一个可变的默认值,该默认值在 ArrayField .
这是必需的参数。
指定数组的基础数据类型和行为。它应该是 Field .例如,它可能是 IntegerField 或 CharField .大多数字段类型都是允许的,但处理关系数据的字段类型除外 (ForeignKey , OneToOneField 和 ManyToManyField )和文件字段 (FileField 和 ImageField ).
可以嵌套数组字段-可以指定 ArrayField 作为 base_field . 例如::
from django.contrib.postgres.fields import ArrayField
from django.db import models
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¶有许多自定义查找和转换 ArrayField . 我们将使用以下示例模型:
from django.contrib.postgres.fields import ArrayField
from django.db import models
class Post(models.Model):
name = models.CharField(max_length=200)
tags = ArrayField(models.CharField(max_length=200), blank=True)
def __str__(self):
return self.name
contains¶这个 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"])
<QuerySet [<Post: First post>, <Post: Second post>]>
>>> Post.objects.filter(tags__contains=["django"])
<QuerySet [<Post: First post>, <Post: Third post>]>
>>> Post.objects.filter(tags__contains=["django", "thoughts"])
<QuerySet [<Post: First post>]>
contained_by¶这是与 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"])
<QuerySet [<Post: First post>, <Post: Second post>]>
>>> Post.objects.filter(tags__contained_by=["thoughts", "django", "tutorial"])
<QuerySet [<Post: First post>, <Post: Second post>, <Post: Third post>]>
overlap¶返回数据与传递的值共享任何结果的对象。使用SQL运算符 && 。例如:
>>> Post.objects.create(name="First post", tags=["thoughts", "django"])
>>> Post.objects.create(name="Second post", tags=["thoughts", "tutorial"])
>>> Post.objects.create(name="Third post", tags=["tutorial", "django"])
>>> Post.objects.filter(tags__overlap=["thoughts"])
<QuerySet [<Post: First post>, <Post: Second post>]>
>>> Post.objects.filter(tags__overlap=["thoughts", "tutorial"])
<QuerySet [<Post: First post>, <Post: Second post>, <Post: Third post>]>
>>> Post.objects.filter(tags__overlap=Post.objects.values_list("tags"))
<QuerySet [<Post: First post>, <Post: Second post>, <Post: Third post>]>
len¶返回数组的长度。之后可用的查找是可用于 IntegerField 。例如:
>>> Post.objects.create(name="First post", tags=["thoughts", "django"])
>>> Post.objects.create(name="Second post", tags=["thoughts"])
>>> Post.objects.filter(tags__len=1)
<QuerySet [<Post: Second post>]>
INDEX将索引转换为数组。可以使用任何非负整数。如果它超过 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")
<QuerySet [<Post: First post>, <Post: Second post>]>
>>> Post.objects.filter(tags__1__iexact="Django")
<QuerySet [<Post: First post>]>
>>> Post.objects.filter(tags__276="javascript")
<QuerySet []>
备注
PostgreSQL在编写原始SQL时对数组字段使用基于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"])
<QuerySet [<Post: First post>, <Post: Second post>]>
>>> Post.objects.filter(tags__0_2__contains=["thoughts"])
<QuerySet [<Post: First post>, <Post: Second post>]>
备注
PostgreSQL在编写原始SQL时对数组字段使用基于1的索引。但是这些切片和 indexes 使用基于0的索引来与Python保持一致。
带索引和切片的多维数组
PostgreSQL在多维数组上使用索引和切片时有一些相当深奥的行为。使用索引来达到最终的基础数据总是有效的,但是大多数其他切片在数据库级别表现得很奇怪,并且Django无法以逻辑的、一致的方式支持它们。
HStoreField¶用于存储键值对的字段。使用的python数据类型是 dict . 键必须是字符串,并且值可以是字符串或空值 (None 在 Python 中)。
要使用此字段,您需要:
添加 'django.contrib.postgres' 在你 INSTALLED_APPS .
Set up the hstore extension 在PostgreSQL中。
你会看到一个错误,比如 can't adapt type 'dict' 如果跳过第一步,或 type "hstore" does not exist 如果跳过第二个。
备注
有时,要求或限制对给定字段有效的键可能很有用。可以使用 KeysValidator .
HStoreField¶除了可以按键查询之外,还有许多自定义查找可用于 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):
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")
<QuerySet [<Dog: Meg>]>
您可以在关键字查找之后链接其他查找:
>>> Dog.objects.filter(data__breed__contains="l")
<QuerySet [<Dog: Rufus>, <Dog: Meg>]>
或使用 F() 用于批注键值的表达式。例如:
>>> from django.db.models import F
>>> rufus = Dog.objects.annotate(breed=F("data__breed"))[0]
>>> rufus.breed
'labrador'
如果要查询的键与另一个查找的名称冲突,则需要使用 hstorefield.contains 查找相反。
备注
还可以使用以下链接来链接键转换: contains , icontains , endswith , iendswith , iexact , regex , iregex , startswith ,以及 istartswith 查找。
警告
由于任何字符串都可以是hstore值中的键,因此除下面列出的字符串以外的任何查找都将被解释为键查找。未引发任何错误。要格外小心打字错误,并且总是检查你的查询是否按你的意愿工作。
contains¶这个 contains 上的查找被覆盖 HStoreField 。返回的对象是那些给定的 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"})
<QuerySet [<Dog: Rufus>, <Dog: Meg>]>
>>> Dog.objects.filter(data__contains={"breed": "collie"})
<QuerySet [<Dog: Meg>]>
contained_by¶这是与 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"})
<QuerySet [<Dog: Meg>, <Dog: Fred>]>
>>> Dog.objects.filter(data__contained_by={"breed": "collie"})
<QuerySet [<Dog: Fred>]>
has_key¶返回数据中给定键所在的对象。使用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")
<QuerySet [<Dog: Meg>]>
has_any_keys¶返回数据中存在任何给定键的对象。使用SQL运算符 ?| 。例如:
>>> Dog.objects.create(name="Rufus", data={"breed": "labrador"})
>>> Dog.objects.create(name="Meg", data={"owner": "Bob"})
>>> Dog.objects.create(name="Fred", data={})
>>> Dog.objects.filter(data__has_any_keys=["owner", "breed"])
<QuerySet [<Dog: Rufus>, <Dog: Meg>]>
has_keys¶返回所有给定键都在数据中的对象。使用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"])
<QuerySet [<Dog: Meg>]>
keys¶返回键数组为给定值的对象。请注意,不能保证顺序是可靠的,因此此转换主要用于与 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"])
<QuerySet [<Dog: Rufus>, <Dog: Meg>]>
values¶返回值数组为给定值的对象。请注意,不能保证顺序是可靠的,因此此转换主要用于与 ArrayField 。使用SQL函数 avals() 。例如:
>>> 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"])
<QuerySet [<Dog: Meg>]>
有五种范围字段类型,对应于PostgreSQL中内置的范围类型。这些字段用于存储一系列值;例如事件的开始和结束时间戳,或者活动适合的年龄范围。
所有范围字段都会转换为 psycopg Range objects 如果不需要边界信息,还可以接受元组作为输入。缺省值为包含下限、排除上限,即 [) (有关的详细信息,请参阅PostgreSQL文档 different bounds )。可以更改非离散范围字段的默认边界 (DateTimeRangeField 和 DecimalRangeField )通过使用 default_bounds 争论。
PostgreSQL规范化一个不指向空范围的范围
为包含的下限和排除的上限指定了相等值的范围,例如 Range(datetime.date(2005, 6, 21), datetime.date(2005, 6, 21)) 或 [4, 4) ,没有积分。保存到数据库时,PostgreSQL会将该值规范化为空,原始绑定值将丢失。看到 PostgreSQL documentation for details .
IntegerRangeField¶存储一系列整数。基于一个 IntegerField 。由一个 int4range 在数据库中,并且一个 django.db.backends.postgresql.psycopg_any.NumericRange 在Python中。
无论保存数据时指定的边界如何,PostgreSQL始终以规范形式返回一个范围,其中包括下限并排除上限,即 [) 。
BigIntegerRangeField¶存储一系列大整数。基于一个 BigIntegerField 。由一个 int8range 在数据库中,并且一个 django.db.backends.postgresql.psycopg_any.NumericRange 在Python中。
无论保存数据时指定的边界如何,PostgreSQL始终以规范形式返回一个范围,其中包括下限并排除上限,即 [) 。
DecimalRangeField¶存储一定范围的浮点值。基于一个 DecimalField 。由一个 numrange 在数据库中,并且一个 django.db.backends.postgresql.psycopg_any.NumericRange 在Python中。
可选的。的价值 bounds 用于列表和元组输入。缺省值为包含下限、排除上限,即 [) (有关的详细信息,请参阅PostgreSQL文档 different bounds )。 default_bounds 不用于 django.db.backends.postgresql.psycopg_any.NumericRange 投入。
DateTimeRangeField¶存储一系列时间戳。基于一个 DateTimeField 。由一个 tstzrange 在数据库中,并且一个 django.db.backends.postgresql.psycopg_any.DateTimeTZRange 在Python中。
可选的。的价值 bounds 用于列表和元组输入。缺省值为包含下限、排除上限,即 [) (有关的详细信息,请参阅PostgreSQL文档 different bounds )。 default_bounds 不用于 django.db.backends.postgresql.psycopg_any.DateTimeTZRange 投入。
DateRangeField¶范围字段有许多自定义查找和转换。它们在上述所有字段上都可用,但我们将使用以下示例模型:
from django.contrib.postgres.fields import IntegerRangeField
from django.db import models
class Event(models.Model):
name = models.CharField(max_length=200)
ages = IntegerRangeField()
start = models.DateTimeField()
def __str__(self):
return self.name
我们还将使用以下示例对象:
>>> import datetime
>>> from django.utils import timezone
>>> now = timezone.now()
>>> Event.objects.create(name="Soft play", ages=(0, 10), start=now)
>>> Event.objects.create(
... name="Pub trip", ages=(21, None), start=now - datetime.timedelta(days=1)
... )
和 NumericRange :
>>> from django.db.backends.postgresql.psycopg_any import NumericRange
与其他PostgreSQL字段一样,有三个标准的包含运算符: contains , contained_by 和 overlap ,使用SQL运算符 @> , <@ 和 && 分别。
contains¶>>> Event.objects.filter(ages__contains=NumericRange(4, 5))
<QuerySet [<Event: Soft play>]>
contained_by¶>>> Event.objects.filter(ages__contained_by=NumericRange(0, 15))
<QuerySet [<Event: Soft play>]>
这个 contained_by 查找也适用于非范围字段类型: SmallAutoField , AutoField , BigAutoField , SmallIntegerField , IntegerField , BigIntegerField , DecimalField , FloatField , DateField ,以及 DateTimeField 。例如:
>>> from django.db.backends.postgresql.psycopg_any import DateTimeTZRange
>>> Event.objects.filter(
... start__contained_by=DateTimeTZRange(
... timezone.now() - datetime.timedelta(hours=1),
... timezone.now() + datetime.timedelta(hours=1),
... ),
... )
<QuerySet [<Event: Soft play>]>
overlap¶>>> Event.objects.filter(ages__overlap=NumericRange(8, 12))
<QuerySet [<Event: Soft play>]>
范围字段支持标准查找: lt , gt , lte 和 gte . 这些并不是特别有用的——它们只在必要时先比较下限,然后比较上限。这也是用于按范围字段排序的策略。最好使用特定的范围比较运算符。
fully_lt¶返回的范围严格小于通过的范围。换句话说,返回范围中的所有点都小于传递范围中的所有点。
>>> Event.objects.filter(ages__fully_lt=NumericRange(11, 15))
<QuerySet [<Event: Soft play>]>
fully_gt¶返回的范围严格大于传递的范围。换句话说,返回范围中的所有点都大于传递范围中的所有点。
>>> Event.objects.filter(ages__fully_gt=NumericRange(11, 15))
<QuerySet [<Event: Pub trip>]>
not_lt¶返回的范围不包含小于传递范围的任何点,即返回范围的下限至少是传递范围的下限。
>>> Event.objects.filter(ages__not_lt=NumericRange(0, 15))
<QuerySet [<Event: Soft play>, <Event: Pub trip>]>
not_gt¶返回的范围不包含任何大于传递范围的点,即返回范围的上限最多为传递范围的上限。
>>> Event.objects.filter(ages__not_gt=NumericRange(3, 10))
<QuerySet [<Event: Soft play>]>
adjacent_to¶返回的范围与传递的范围共享一个界限。
>>> Event.objects.filter(ages__adjacent_to=NumericRange(10, 21))
<QuerySet [<Event: Soft play>, <Event: Pub trip>]>
范围字段支持多个额外的查找。
startswith¶返回的对象具有给定的下限。无法链接到基字段的有效查找。
>>> Event.objects.filter(ages__startswith=21)
<QuerySet [<Event: Pub trip>]>
endswith¶返回的对象具有给定的上限。无法链接到基字段的有效查找。
>>> Event.objects.filter(ages__endswith=10)
<QuerySet [<Event: Soft play>]>
isempty¶返回的对象是空范围。可以链接到 BooleanField .
>>> Event.objects.filter(ages__isempty=True)
<QuerySet []>
lower_inc¶返回具有包容性或排他性下限的对象,具体取决于传递的布尔值。可以链接到有效查找 BooleanField 。
>>> Event.objects.filter(ages__lower_inc=True)
<QuerySet [<Event: Soft play>, <Event: Pub trip>]>
lower_inf¶返回具有无界(无限)或有界下限的对象,具体取决于传递的布尔值。可以链接到有效查找 BooleanField 。
>>> Event.objects.filter(ages__lower_inf=True)
<QuerySet []>
upper_inc¶返回具有包容性或排他性上限的对象,具体取决于传递的布尔值。可以链接到有效查找 BooleanField 。
>>> Event.objects.filter(ages__upper_inc=True)
<QuerySet []>
upper_inf¶返回具有无界(无限)或有界上界的对象,具体取决于传递的布尔值。可以链接到有效查找 BooleanField 。
>>> Event.objects.filter(ages__upper_inf=True)
<QuerySet [<Event: Pub trip>]>
PostgreSQL允许定义自定义范围类型。Django的模型和表单字段实现使用下面的基类,并且 psycopg 提供了一种 register_range() 以允许使用自定义范围类型。
模型范围字段的基类。
要使用的模型字段类。
要使用的范围类型。
要使用的窗体字段类。应该是的子类 django.contrib.postgres.forms.BaseRangeField .
PostgreSQL提供了一组可以与范围数据类型一起使用的SQL运算符(请参阅 the PostgreSQL documentation for the full details of range operators ).这个类的目的是作为避免拼写错误的方便方法。操作员名称与相应查找的名称重叠。
class RangeOperators:
EQUAL = "="
NOT_EQUAL = "<>"
CONTAINS = "@>"
CONTAINED_BY = "<@"
OVERLAPS = "&&"
FULLY_LT = "<<"
FULLY_GT = ">>"
NOT_LT = "&>"
NOT_GT = "&<"
ADJACENT_TO = "-|-"
如果 True (默认),下限是包含的 '[' ,否则就是独家的 '(' 。
如果 False (默认),上限是排他性的 ')' ,否则就是包容的 ']' 。
A RangeBoundary() 表达表示范围边界。它可以与预期边界的自定义范围函数一起使用,例如定义边界 ExclusionConstraint 。看见 the PostgreSQL documentation for the full details 。
5月 28, 2025