PostgreSQL 固有のモデルフィールド¶
これらのフィールドは全て django.contrib.postgres.fields
モジュールから利用できます。
これらのフィールドにインデックスを付ける¶
Index
と Field.db_index
は両方とも B-tree インデックスを作成しますが、複雑なデータ型をクエリする際にはあまり役立ちません。 GinIndex
や GistIndex
などのインデックスの方が適しています。ただし、適切なインデックスの選択は使用しているクエリに依存します。一般的には、GiST は 範囲フィールド や HStoreField
には適しており、GIN は ArrayField
に役立つかもしれません。
ArrayField
¶
- class ArrayField(base_field, size=None, **options)¶
データのリストを格納するためのフィールドです。ほとんどのフィールドタイプを使用でき、
base_field
として別のフィールドインスタンスを渡します。size
を指定することもできます。ArrayField
は、多次元配列を格納するためにネストすることもできます。フィールドに
default
を与える場合は、それがlist
(空のデフォルトの場合) やリストを返す呼び出し可能オブジェクト (関数など) のような呼び出し可能オブジェクトであることを確認してください。default=[]
を誤って使用すると、すべてのArrayField
インスタンスで共有される変更可能なデフォルトが作成されます。- base_field¶
これは必須の引数です。
配列のベースとなるデータ型や動作を指定します。これは、
Field
のサブクラスのインスタンスである必要があります。例えばIntegerField
やCharField
などが考えられます。ほとんどのフィールドタイプが許容されますが、リレーショナルデータを処理するもの (ForeignKey
,OneToOneField
,ManyToManyField
) やファイルフィールド (FileField
,ImageField
) は除外されます。配列フィールドは入れ子にできます。
base_field
としてArrayField
のインスタンスを指定できます。たとえば: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, )
データベースとモデル間の値の変換、データと設定の検証、シリアライズはすべて、基盤となるベースフィールドに委譲されます。
- 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],
]
)
不規則な形状が必要な場合は、基になるフィールドをnullable にし、値を 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
¶
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_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>]>
インデックスのトランスフォーム¶
インデックスは配列内のインデックスに変換されます。非負の整数ならどれでも使用できます。配列の 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
で使用されるインデックスは、Pythonとの一貫性を保つために0から始まるインデックスを使用します。
スライス トランスフォーム¶
スライス トランスフォームは、配列の一部を切り取ります。 2つの非負整数をアンダースコアで区切って使用できます。トランスフォーム後に利用可能なルックアップは変わりません。 例を挙げると、
>>> 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
で使用されるスライスは、Pythonとの一貫性を保つために0から始まるインデックスを使用します。
インデックスとスライスを使用した多次元配列
PostgreSQL は、多次元配列でインデックスやスライスを使うときに、かなり難解な動作をします。最終的な基礎データまで到達するためにインデックスを使うのは常にうまくいきますが、他のほとんどのスライスはデータベースレベルで奇妙な動作をするので、 Django が論理的で一貫性のある方法でサポートすることはできません。
HStoreField
¶
- class HStoreField(**options)¶
キーと値のペアを格納するためのフィールド。Python のデータ型は
dict
です。キーは文字列でなければならず、値は文字列または NULL (Python ではNone
) でなければなりません。このフィールドを使用するには、次のようにします:
INSTALLED_APPS
に'django.contrib.postgres'
を追加します。PostgreSQL の hstore 拡張 を設定します。
最初のステップをスキップすると
can't adapt type 'dict'
というエラーが表示され、2番目のステップをスキップすると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の組み込み範囲型に対応する5つの範囲フィールド型があります。これらのフィールドは値の範囲を格納するために使用されます。例えば、イベントの開始と終了のタイムスタンプや、アクティビティに適した年齢の範囲などです。
すべての範囲フィールドはPythonでは psycopg Range オブジェクト に変換されますが、境界情報が不要な場合はタプルを入力として受け付けます。デフォルトは下界を含み、上界を含まない [)
です (different bounds の詳細についてはPostgreSQLのドキュメントを参照してください) 。離散範囲でないフィールド (DateTimeRangeField
と DecimalRangeField
) のデフォルトの境界は default_bounds
引数で変更できます。
IntegerRangeField
¶
- class IntegerRangeField(**options)¶
整数の範囲を格納します。
IntegerField
に基づいています。データベースではint4range
で表現され、 Python ではdjango.db.backends.postgresql.psycopg_any.NumericRange
で表現されます。データ保存時に指定された境界に関係なく、PostgreSQLは常に下界を含み上界を除いた正規形、つまり
[)
で範囲を返します。
BigIntegerRangeField
¶
- class BigIntegerRangeField(**options)¶
大きな整数の範囲を格納します。
BigIntegerField
に基づいています。データベースではint8range
で表現され、 Python ではdjango.db.backends.postgresql.psycopg_any.NumericRange
で表現されます。データ保存時に指定された境界に関係なく、PostgreSQLは常に下界を含み上界を除いた正規形、つまり
[)
で範囲を返します。
DecimalRangeField
¶
- class DecimalRangeField(default_bounds='[)', **options)¶
浮動小数点値の範囲を格納します。
DecimalField
に基づいています。データベースではnumrange
で表現され、Python ではdjango.db.backends.postgresql.psycopg_any.NumericRange
で表現されます。- default_bounds¶
オプション。リストとタプルの入力に対する
bounds
の値。デフォルトは下限を含み、上限を除く[)
です (different bounds の詳細については PostgreSQL のドキュメント を参照してください)。default_bounds
はdjango.db.backends.postgresql.psycopg_any.NumericRange
入力には使用されません。
DateTimeRangeField
¶
- class DateTimeRangeField(default_bounds='[)', **options)¶
タイムスタンプの範囲を格納します。
DateTimeField
に基づいています。データベースではtstzrange
で表現され、Python ではdjango.db.backends.postgresql.psycopg_any.DateTimeTZRange
で表現されます。- default_bounds¶
オプション。リストとタプルの入力に対する
bounds
の値。デフォルトは下限を含み、上限を除く[)
です (different bounds の詳細については PostgreSQL のドキュメント を参照してください)。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 フィールドと同様に、3つの標準の包含演算子があります。 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
, and 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()
を提供しています。
- class RangeField(**options)¶
モデル範囲フィールドの基底クラス。
- base_field¶
使用するモデルフィールドクラス。
- range_type¶
使用する範囲のタイプ。
- form_field¶
使用するフォームフィールドクラス。これは
django.contrib.postgres.forms.BaseRangeField
のサブクラスである必要があります。
範囲演算子¶
- class RangeOperators¶
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() 式¶
- class RangeBoundary(inclusive_lower=True, inclusive_upper=False)¶
- inclusive_lower¶
True
(デフォルト) の場合、下限値は包含される'['
であり、そうでない場合は非包含'('
です。
- inclusive_upper¶
False
(デフォルト) なら、上限は非包含')'
となります。それ以外の場合は包含']'
となります。
RangeBoundary()
式は範囲の境界を表します。これは、範囲の境界を期待するカスタム範囲関数と一緒に使用できます。たとえば、 ExclusionConstraint
を定義する際に使用されます。詳細は PostgreSQLのドキュメント を参照してください。