PostgreSQL 特有模型字段Link to this heading
所有这些字段都可以从 django.contrib.postgres.field 模块中获得。
对这些字段进行索引Link to this heading
Index 和 Field.db_index 都创建了一个 B 树索引,在查询复杂的数据类型时并不是特别有用。像 GinIndex 和 GistIndex 这样的索引比较适合,不过索引的选择取决于你使用的查询。一般来说,GiST 可能是 range 字段 和 HStoreField 的好选择,而 GIN 可能对 ArrayField 有帮助。
ArrayFieldLink to this heading
- class ArrayField(base_field, size=None, **options)Link to this definition
一个用于存储数据列表的字段。大多数字段类型都可以使用,你可以通过另一个字段实例作为
base_field。你也可以指定一个size。ArrayField可以嵌套来存储多维数组。如果你给字段一个
default,确保它是一个可调用对象,比如list(对于一个空的默认值),或者一个返回一个列表的可调用对象(比如一个函数)。错误地使用default=[]会创建一个可变的默认值,这个默认值在ArrayField的所有实例之间共享。- base_fieldLink to this definition
这是一个必要的参数。
Specifies the underlying data type and behavior for the array. It should be an instance of a subclass of
Field. For example, it could be anIntegerFieldor aCharField. Most field types are permitted, with the exception of those handling relational data (ForeignKey,OneToOneFieldandManyToManyField) and file fields (FileFieldandImageField).可以嵌套数组字段——你可以指定一个
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, )数据库和模型之间的值的转换、数据和配置的验证以及序列化都是委托给底层基础字段的。
- sizeLink to this definition
这是一个可选的参数。
如果传入,数组将有一个指定的最大大小。这将被传递给数据库,尽管 PostgreSQL 目前并没有强制执行这个限制。
查询 ArrayFieldLink to this heading
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
containsLink to this heading
ArrayField 上重写了 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__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_byLink to this heading
这是 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>]>
overlapLink to this heading
返回数据与传递的值共享任何结果的对象。使用 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>]>
lenLink to this heading
返回数组的长度。之后可用的查询与 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>]>
索引转换Link to this heading
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 []>
切片转换Link to this heading
Slice 转换获取数组的一个切片。可以使用两个非负整数,用一个下划线分隔。转换后可用的查询不会改变。例如:
>>> 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>]>
HStoreFieldLink to this heading
- class HStoreField(**options)Link to this definition
一个用于存储键值对的字段。使用的 Python 数据类型是
dict。键必须是字符串,值可以是字符串或空值(Python 中的None)。要使用该字段,你需要:
在你的
INSTALLED_APPS中增加'django.contrib.postgres'。在 PostgreSQL 中 安装 hstore 扩展。
如果你跳过第一步,你会看到一个错误,比如
can't adapt type 'dict',如果你跳过第二步,你会看到type "hstore" does not exist。
查询 HStoreFieldLink to this heading
除了按键查询的功能外,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
键查找Link to this heading
要根据给定的键查询,您可以将该键用作查找名称:
>>> 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 查找来代替。
containsLink to this heading
HStoreField 上重写了 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__contains={"owner": "Bob"})
<QuerySet [<Dog: Rufus>, <Dog: Meg>]>
>>> Dog.objects.filter(data__contains={"breed": "collie"})
<QuerySet [<Dog: Meg>]>
contained_byLink to this heading
这是 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_keyLink to this heading
返回包含给定键的数据的对象。使用 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_keysLink to this heading
返回其中任何给定键存在于数据中的对象。使用 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_keysLink to this heading
返回其中所有给定键都存在于数据中的对象。使用 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>]>
keysLink to this heading
返回键数组与给定值相等的对象。请注意,顺序不能保证可靠,因此此转换主要用于与 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>]>
valuesLink to this heading
返回值数组与给定值相等的对象。请注意,顺序不能保证可靠,因此此转换主要用于与 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>]>
范围字段Link to this heading
有五种范围字段类型,对应 PostgreSQL 中内置的范围类型。这些字段用来存储一个范围的值,例如一个事件的开始和结束时间戳,或者一个活动适合的年龄范围。
所有的范围字段在 Python 中都会翻译成 psycopg Range 对象,但如果不需要边界信息,也可以接受元组作为输入。默认是包含下界,不包含上界,即 [) (有关 不同边界 的详细信息,请参阅 PostgreSQL 文档)。对于非离散范围字段(例如 DateTimeRangeField 和 DecimalRangeField),可以使用 default_bounds 参数更改默认边界。
IntegerRangeFieldLink to this heading
- class IntegerRangeField(**options)Link to this definition
存储一组整数范围。基于
IntegerField。在数据库中由int4range表示,在 Python 中由django.db.backends.postgresql.psycopg_any.NumericRange表示。无论在保存数据时指定的边界是什么,PostgreSQL 总是以规范的形式返回一个包括下限和排除上限的范围,即
[)。
BigIntegerRangeFieldLink to this heading
- class BigIntegerRangeField(**options)Link to this definition
存储一组大整数范围。基于
BigIntegerField。在数据库中由int8range表示,在 Python 中由django.db.backends.postgresql.psycopg_any.NumericRange表示。无论在保存数据时指定的边界是什么,PostgreSQL 总是以规范的形式返回一个包括下限和排除上限的范围,即
[)。
DecimalRangeFieldLink to this heading
- class DecimalRangeField(default_bounds='[)', **options)Link to this definition
存储一组浮点数值范围。基于
DecimalField。在数据库中由numrange表示,在 Python 中由django.db.backends.postgresql.psycopg_any.NumericRange表示。- default_boundsLink to this definition
可选。列表和元组输入的
bounds值。默认为包含下界,不包含上界,即[)(有关 不同边界 的详细信息,请参阅 PostgreSQL 文档)。default_bounds不用于django.db.backends.postgresql.psycopg_any.NumericRange输入。
DateTimeRangeFieldLink to this heading
- class DateTimeRangeField(default_bounds='[)', **options)Link to this definition
存储一组时间戳范围。基于
DateTimeField。在数据库中由tstzrange表示,在 Python 中由django.db.backends.postgresql.psycopg_any.DateTimeTZRange表示。- default_boundsLink to this definition
可选。列表和元组输入的
bounds值。默认为包含下界,不包含上界,即[)(有关 不同边界 的详细信息,请参阅 PostgreSQL 文档)。default_bounds不用于django.db.backends.postgresql.psycopg_any.DateTimeTZRange输入。
DateRangeFieldLink to this heading
- class DateRangeField(**options)Link to this definition
存储一组日期范围。基于
DateField。在数据库中由daterange表示,在 Python 中由django.db.backends.postgresql.psycopg_any.DateRange表示。无论在保存数据时指定的边界是什么,PostgreSQL 总是以规范的形式返回一个包括下限和排除上限的范围,即
[)。
查询范围字段Link to this heading
对于范围字段,有许多自定义查找和转换。它们适用于所有上述字段,但我们将使用以下示例模型:
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
包含函数Link to this heading
与其他 PostgreSQL 字段一样,有三个标准的包含运算符。contains、contained_by 和 overlap,分别使用 SQL 运算符 @>、<@ 和 &&。
containsLink to this heading
>>> Event.objects.filter(ages__contains=NumericRange(4, 5))
<QuerySet [<Event: Soft play>]>
contained_byLink to this heading
>>> 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>]>
overlapLink to this heading
>>> Event.objects.filter(ages__overlap=NumericRange(8, 12))
<QuerySet [<Event: Soft play>]>
比较函数Link to this heading
范围字段支持标准查询:lt、gt、lte 和 gte。这些并没有特别大的帮助——它们先比较下界,然后在必要时才比较上界。这也是用于按范围字段排序的策略。最好是使用特定的范围比较运算符。
fully_ltLink to this heading
返回的范围严格小于传入的范围。换句话说,返回范围内的所有点都小于传入范围内的所有点。
>>> Event.objects.filter(ages__fully_lt=NumericRange(11, 15))
<QuerySet [<Event: Soft play>]>
fully_gtLink to this heading
返回的范围严格大于传入的范围。换句话说,返回范围内的所有点都大于传入范围内的所有点。
>>> Event.objects.filter(ages__fully_gt=NumericRange(11, 15))
<QuerySet [<Event: Pub trip>]>
not_ltLink to this heading
返回的范围不包含任何小于传入范围的点,即返回范围的下界至少是传入范围的下界。
>>> Event.objects.filter(ages__not_lt=NumericRange(0, 15))
<QuerySet [<Event: Soft play>, <Event: Pub trip>]>
not_gtLink to this heading
返回的范围不包含任何大于传入范围的点,也就是说,返回的范围的上界最多就是传入范围的上界。
>>> Event.objects.filter(ages__not_gt=NumericRange(3, 10))
<QuerySet [<Event: Soft play>]>
adjacent_toLink to this heading
返回的范围与传入的范围共享一个边界。
>>> Event.objects.filter(ages__adjacent_to=NumericRange(10, 21))
<QuerySet [<Event: Soft play>, <Event: Pub trip>]>
使用边界进行查询Link to this heading
范围字段支持几个额外的查找。
startswithLink to this heading
返回的对象具有给定的下界。可以链入基础字段的有效查找。
>>> Event.objects.filter(ages__startswith=21)
<QuerySet [<Event: Pub trip>]>
endswithLink to this heading
返回的对象具有给定的上界。可以链入基础字段的有效查找。
>>> Event.objects.filter(ages__endswith=10)
<QuerySet [<Event: Soft play>]>
isemptyLink to this heading
返回的对象是空的范围。可以链到有效的查找 BooleanField。
>>> Event.objects.filter(ages__isempty=True)
<QuerySet []>
lower_incLink to this heading
根据传递的布尔值,返回具有包含或不包含下界的对象。可以链到有效的查找 BooleanField 的对象。
>>> Event.objects.filter(ages__lower_inc=True)
<QuerySet [<Event: Soft play>, <Event: Pub trip>]>
lower_infLink to this heading
根据传递的布尔值,返回具有无界(无限)或仅有下界的对象。可以链到有效的查找 BooleanField。
>>> Event.objects.filter(ages__lower_inf=True)
<QuerySet []>
upper_incLink to this heading
根据传递的布尔值,返回具有包含或不包含上界的对象。可以链到有效的查找 BooleanField 的对象。
>>> Event.objects.filter(ages__upper_inc=True)
<QuerySet []>
upper_infLink to this heading
根据传递的布尔值,返回具有无界(无限)或仅有上界的对象。可以链到有效的查找 BooleanField。
>>> Event.objects.filter(ages__upper_inf=True)
<QuerySet [<Event: Pub trip>]>
定义自己的范围类型Link to this heading
PostgreSQL 允许定义自定义范围类型。Django 的模型和表单字段实现使用以下基类,并且 psycopg 提供了一个 register_range() 函数来允许使用自定义范围类型。
- class RangeField(**options)Link to this definition
模型范围字段的基类。
- base_fieldLink to this definition
要使用的模型字段类。
- range_typeLink to this definition
要使用的范围类型。
- form_fieldLink to this definition
要使用的表单字段类。应该是
django.contrib.postgres.forms.BaseRangeField的子类。
- class django.contrib.postgres.forms.BaseRangeFieldLink to this definition
表范围字段的基类。
- base_fieldLink to this definition
要使用的表字段。
- range_typeLink to this definition
要使用的范围类型。
范围操作Link to this heading
- class RangeOperatorsLink to this definition
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 = "-|-"
RangeBoundary() 表达式Link to this heading
- class RangeBoundary(inclusive_lower=True, inclusive_upper=False)Link to this definition
- inclusive_lowerLink to this definition
如果
True(默认),则下界为包含'[',否则为不包含'('。
- inclusive_upperLink to this definition
如果
False(默认),则上界为包含')',否则为不包含']'。
RangeBoundary() 表达式表示范围边界。它可以与自定义的范围函数一起使用,预期边界,例如定义 ExclusionConstraint。参见 `the PostgreSQL documentation for the full details `_ 。