所有这些字段都可以从django.contrib.postgres.fields
模块获取。
ArrayField
¶ArrayField
(base_field, size=None, **options)[source]¶用于存储数据列表的字段。 可以使用大多数字段类型,只需将另一个字段实例传递为base_field
。 您也可以指定size
。 ArrayField
可以嵌套存储多维数组。
如果您将字段设置为default
,请确保它是可调用的,例如list
(空默认)或可返回列表(如函数)的可调用。 错误地使用default=[]
创建了一个可变的默认值,它在ArrayField
的所有实例之间共享。
base_field
¶这是必需的参数。
指定数组的底层数据类型和行为。 它应该是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,
)
数据库和模型之间的值转换,数据和配置的验证以及序列化都被委派给底层基本字段。
size
¶这是一个可选参数。
如果传递,数组将具有指定的最大大小。 这将被传递到数据库,虽然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.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
¶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'])
>>> 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>]>
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>]>
这类变换允许您在查询中索引到数组。 可以使用任何非负整数。 如果超过数组的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 []>
注
在编写原始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'])
<QuerySet [<Post: First post>, <Post: Second post>]>
>>> Post.objects.filter(tags__0_2__contains=['thoughts'])
<QuerySet [<Post: First post>, <Post: Second post>]>
注
在编写原始SQL时,PostgreSQL对数组字段使用基于1的索引。
然而,这些切片和indexes
使用基于0的索引来与Python一致。
具有索引和切片的多维数组
当在多维数组上使用索引和切片时,PostgreSQL有一些相当深奥的行为。 它将始终使用索引来达到最终的底层数据,但大多数其他切片在数据库级别上表现奇怪,不能以Django的逻辑一致方式支持。
CIText
字段¶CIText
(**options)[source]¶一个mixin来创建由citext类型支持的不区分大小写的文本字段。 在使用之前,请阅读性能注意事项。
要使用citext
,在第一个CreateModel
迁移操作之前,请在PostgreSQL中使用CITextExtension
操作setup the citext extension。
提供了使用mixin的几个字段:
CITextField
(**options)[source]¶这些字段分别为CharField
,EmailField
和TextField
。
max_length
不会在数据库中执行,因为citext
的行为类似于PostgreSQL的text
类型。
HStoreField
¶HStoreField
(**options)[source]¶用于存储键值对的字段。 使用的Python数据类型是dict
。 键必须是字符串,值可以是字符串或空值(Python中的None
)。
要使用此字段,您需要:
INSTALLED_APPS
中添加'django.contrib.postgres'
。你会看到一个错误,如不能 适应 类型 'dict'
如果您跳过第一步,或类型 “hstore” 不 / t10>
如果你跳过第二个。
增加了存储空值的功能。 以前,他们被投入了弦。
注
在某些情况下,可能需要或限制对给定字段有效的键。 这可以使用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): # __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')
<QuerySet [<Dog: Meg>]>
您可以在键查找后链接其他查找:
>>> Dog.objects.filter(data__breed__contains='l')
<QuerySet [<Dog: Rufus>, <Dog: Meg>]>
如果您希望查询的键与另一个查找的名称冲突,则需要使用hstorefield.contains
查找。
警告
因为任何字符串都可能是hstore值中的键,除了下面列出的以外的任何查找都将被解释为键查找。 不会产生错误。 请特别小心输入错误,并始终检查您的查询工作,因为你打算。
contains
¶在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'})
<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函数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'])
<QuerySet [<Dog: Meg>]>
JSONField
¶JSONField
(encoder=None, **options)[source]¶用于存储JSON编码数据的字段。 在Python中,数据以Python本机格式表示:字典,列表,字符串,数字,布尔和None
。
encoder
¶一个可选的JSON编码类,用于序列化标准JSON序列化程序(datetime
,uuid
等)不支持的数据类型。 例如,你可以使用DjangoJSONEncoder
类或json.JSONEncoder
的任何其它子类。
当从数据库检索该值时,它将采用自定义编码器选择的格式(通常是字符串),因此需要采取额外的步骤才能将值转换回初始数据类型(Model.from_db()
和Field.from_db_value()
是两个hook,可以用于此目的)。 反序列化需要考虑无法确定输入类型的情况。
例如,你正在返回datetime
,它实际上是一个字符串,只是恰好与datetime
所选择的格式相同。
如果你给这个字段一个default
,那么确保它是一个可调用的,例如dict
(一个空的默认值)或一个可以返回一个dict(如一个函数)的callable。 错误地使用default={}
创建了一个可变的默认值,它在JSONField
的所有实例之间共享。
注
PostgreSQL有两种本机基于JSON的数据类型:json
和jsonb
。
它们之间的主要区别是它们如何被存储以及如何被查询。 PostgreSQL的json
字段存储为JSON的原始字符串表示形式,并且必须在基于密钥查询时即时解码。 jsonb
字段的存储基于JSON的实际结构,这样允许索引。 在写入jsonb
字段时,这种权衡的成本相对较小。 JSONField
使用jsonb
。
因此,此字段需要PostgreSQL≥9.4。
JSONField
¶我们将使用以下示例模型:
from django.contrib.postgres.fields import JSONField
from django.db import models
class Dog(models.Model):
name = models.CharField(max_length=200)
data = JSONField()
def __str__(self): # __unicode__ on Python 2
return self.name
要根据给定的字典键查询,只需使用该键作为查找名称:
>>> Dog.objects.create(name='Rufus', data={
... 'breed': 'labrador',
... 'owner': {
... 'name': 'Bob',
... 'other_pets': [{
... 'name': 'Fishy',
... }],
... },
... })
>>> Dog.objects.create(name='Meg', data={'breed': 'collie'})
>>> Dog.objects.filter(data__breed='collie')
<QuerySet [<Dog: Meg>]>
多个键可以链接在一起以形成路径查找:
>>> Dog.objects.filter(data__owner__name='Bob')
<QuerySet [<Dog: Rufus>]>
如果键是整数,它将被解释为数组中的索引查找:
>>> Dog.objects.filter(data__owner__other_pets__0__name='Fishy')
<QuerySet [<Dog: Rufus>]>
如果您希望通过与另一个查找的名称进行冲突查询的密钥,请改用jsonfield.contains
查找。
如果仅使用一个键或索引,则使用SQL运算符->
。 如果使用多个操作符,则使用#>
运算符。
警告
由于任何字符串可能是JSON对象中的一个键,所以除了下面列出的任何查找都将被解释为键查找。 不会产生错误。 请特别小心输入错误,并始终检查您的查询工作,因为你打算。
JSONField
shares lookups relating to
containment and keys with HStoreField
.
contains
(接受任何JSON而不是字典字典)contained_by
(接受任何JSON而不是字典的字典)对象的has_key
has_any_keys
has_keys
有五个范围字段类型,对应于PostgreSQL中的内置范围类型。 这些字段用于存储值的范围;例如事件的开始和结束时间戳,或活动适合的年龄范围。
所有范围字段都转换为python中的psycopg2 Range objects,但如果不需要边界信息,也接受元组作为输入。 默认为下限,包括上限;也就是[)
。
IntegerRangeField
¶IntegerRangeField
(**options)[source]¶存储整数范围。 基于IntegerField
。 由数据库中的int4range
和Python中的NumericRange
表示。
无论在保存数据时指定的边界如何,PostgreSQL总是返回一个包含下限的规范形式的范围,并排除上限;那是[)
。
BigIntegerRangeField
¶BigIntegerRangeField
(**options)[source]¶存储大整数的范围。 基于BigIntegerField
。 由数据库中的int8range
和Python中的NumericRange
表示。
无论在保存数据时指定的边界如何,PostgreSQL总是返回一个包含下限的规范形式的范围,并排除上限;那是[)
。
FloatRangeField
¶FloatRangeField
(**options)[source]¶存储浮点值的范围。 基于FloatField
。 在数据库中由numrange
表示,在Python中由NumericRange
表示。
DateTimeRangeField
¶DateTimeRangeField
(**options)[source]¶存储时间戳范围。 基于DateTimeField
。 在数据库中由tstzrange
表示,在Python中使用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): # __unicode__ on Python 2
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 psycopg2.extras 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
查找也可用于非范围字段类型:IntegerField
,BigIntegerField
,FloatField
,DateField
和DateTimeField
。 像这样:
>>> from psycopg2.extras 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 []>
PostgreSQL允许定义自定义范围类型。 Django的模型和表单字段实现使用下面的基类,psycopg2提供了一个register_range()
以允许使用自定义范围类型。
2017年9月6日