QuerySet API リファレンス¶
このドキュメントでは、QuerySet API の詳細を説明しています。モデル と データベースクエリ ガイドにある説明を前提としていますので、このドキュメントを読む前にこの 2 つを読んでおいた方がよいでしょう。
このリファレンスでは、 データベースクエリガイド で提供された Blogモデルの例 を使用します。
QuerySet が評価されるタイミング¶
内部的には、 QuerySet は実際にデータベースにアクセスすることなく、構築、フィルタリング、スライス、受け渡しを行うことができます。クエリセットを評価するための操作が行われない限り、実際のデータベースへのアクセスは発生しません。
あなたは次のような方法で QuerySet を評価することができます:
イテレーション。
QuerySetはイテラブルで、初めてイテレートした時にデータベースのクエリを実行します。たとえば、これはデータベースにある全エントリのheadline属性を出力するプログラムです:for e in Entry.objects.all(): print(e.headline)
メモ: 1つ以上の結果が存在するかどうかを判定したいだけなら、これは使わないでください。
exists()を使った方が効率的です。非同期イテレーション.
QuerySetはasync forを使ってイテレートすることもできます:async for e in Entry.objects.all(): results.append(e)
クエリセットの同期的・非同期的イテレータは、同じキャッシュを共有します。
スライス。 QuerySet の要素数を制限する で説明されているとおり、
QuerySetはPythonのリストスライスを用いてスライスできます。未評価のQuerySetをスライスすると、通常は新たな未評価のQuerySetが返されます。しかし、スライスの "step" パラメータを使用した場合、Djangoはデータベースクエリを実行し、リストを返します。評価されたQuerySetをスライスした場合も同様にリストが返されます。未評価の
QuerySetをスライスして別の未評価のQuerySetが返されても、それをさらに変更すること(たとえば、さらにフィルタを追加したり、順序を変更したりすること)は許されていないことに気を付けてください。これは、その操作がSQLに正しく変換されず、明確な意味を持たないためです。Pickle 化/キャッシュ化。 詳細については、後述の pickling QuerySets を参照してください。結果がデータベースから読み出されることが、このセクションの目的として重要なことです。
repr()。
QuerySetはrepr()が呼び出された時点で評価されます。これはPythonの対話型インタプリタでの利便性を図るためで、APIを対話的に使用する際にクエリの結果をすぐに確認できます。len()。
QuerySetはlen()を呼び出した時点で評価されます。想像される通り、この操作は結果のリストの長さを返します。メモ: セット内のレコード数を決定したいだけであれば(そして実際のオブジェクトが必要ないのであれば)、SQLの
SELECT COUNT(*)を使ってデータベースレベルでハンドルする方がより効率的です。Djangoはまさにこの理由からcount()メソッドを提供しています。list()。
list()を呼び出すことで、QuerySetの評価を強制します。たとえば:entry_list = list(Entry.objects.all())
bool()。
bool(),or,andまたはif文を使用してブール値としてQuerySetをテストすると、クエリが実行されます。QuerySetも少なくとも1つ以上の結果が含まれればTrueとなり、そうでなければFalseになります。例えば:if Entry.objects.filter(headline="Test"): print("There is at least one Entry with the headline Test")
注意: もしクエリの結果が少なくとも1つ存在するかどうかを確認したいだけであれば(そして実際のオブジェクトを必要としないのであれば)、
exists()を使うべきです。
QuerySet の Pickle 化¶
QuerySet を pickle 化するとき、pickle化の前にすべての結果がメモリにロードされるように強制されます。キャッシュされたクエリセットがリロードされた時、結果がすでに存在し、使用できる状態になっていることが望ましいからです(データベースからの読み込みには時間がかかるので、キャッシュとしての目的を達成できません)。つまり、 QuerySet のpickle化を解除すると、解除した時点でデータベースにある結果ではなく、pickle化した時点での結果が出力されることになります。
もし、後でデータベースから QuerySet を再生成するために必要な情報だけを取り出したい場合は、 QuerySet の query を属性を取り出してください。そうすることで、以下のようなコードで本来の QuerySet (結果を読み込む前の状態)を再現できます:
>>> import pickle
>>> query = pickle.loads(s) # Assuming 's' is the pickled string.
>>> qs = MyModel.objects.all()
>>> qs.query = query # Restore the original 'query'.
query 属性は不透明なオブジェクトです。これは内側でのクエリ構築を表すもので、公開APIの一部ではありません。しかし、ここで説明しているように、この属性の内容のpickle化・pickle化の解除は安全に行うことができます(完全にサポートもされています)。
QuerySet.values_list() における制限
pickle化された query 属性を使って QuerySet.values_list() を再生成すると、返り値は QuerySet.values() に置き換えられます:
>>> import pickle
>>> qs = Blog.objects.values_list("id", "name")
>>> qs
<QuerySet [(1, 'Beatles Blog')]>
>>> reloaded_qs = Blog.objects.all()
>>> reloaded_qs.query = pickle.loads(pickle.dumps(qs.query))
>>> reloaded_qs
<QuerySet [{'id': 1, 'name': 'Beatles Blog'}]>
QuerySet API¶
これが QuerySet の正式な宣言です:
- class QuerySet(model=None, query=None, using=None, hints=None)[ソース]¶
通常、
QuerySetを操作する際には フィルタの連結 を使用します。これを実現するために、ほとんどのQuerySetのメソッドは新たなクエリセットを返します。これらのメソッドについては、このセクションで後ほど詳しく説明します。QuerySetクラスは、イントロスペクションのために以下のパブリックな属性を持っています:- ordered[ソース]¶
QuerySetがorder_by()やモデルのデフォルトの順序指定によって並び替えられた場合にTrueとなります。それ以外のときはFalseになります。
注釈
QuerySetのqueryパラメータは、特殊なクエリのサブクラスが内部のクエリ状態を再構築できるようにするために存在します。このパラメータの値はクエリの状態の不透明な表現であり、パブリックAPIの一部ではありません。
新しい QuerySets を返すメソッド¶
QuerySet が返す結果の種類や、SQLクエリの実行方法を変更するための、さまざまな QuerySet の改良メソッドをDjangoは提供します。
注釈
これらのメソッドはデータベースクエリを実行しないので、非同期コードで実行しても 安全 であり、非同期処理専用のメソッドは存在しません。
filter()¶
- filter(*args, **kwargs)¶
与えられたルックアップパラメータにマッチする新しい QuerySet を返します。
ルックアップパラメータ (**kwargs) は以下の Field lookups で説明されているフォーマットに従わなければなりません。複数のパラメータは、元となるSQLステートメントでは AND によって結合されます。
より複雑なクエリを実行したい場合(たとえば OR ステートメントを含むクエリ)は、 Q オブジェクト (*args) を使用してください。
exclude()¶
- exclude(*args, **kwargs)¶
与えられたルックアップパラメータにマッチ しない 新しい QuerySet を返します。
ルックアップパラメータ (**kwargs) は下記の Field lookups で説明されているフォーマットに従わなければなりません。複数のパラメータは、元となるSQLステートメントでは AND によって結合され、全体が NOT() によって囲まれます。
この例では pub_date が 2005-1-3より新しく、 headline が "Hello" であるようなエントリーを除外しています:
Entry.objects.exclude(pub_date__gt=datetime.date(2005, 1, 3), headline="Hello")
SQL文では、次のように評価されます:
SELECT ...
WHERE NOT (pub_date > '2005-1-3' AND headline = 'Hello')
この例では pub_date が 2005-1-3より新しいか、 headline が "Hello" であるようなエントリーを除外しています:
Entry.objects.exclude(pub_date__gt=datetime.date(2005, 1, 3)).exclude(headline="Hello")
SQL文では、次のように評価されます:
SELECT ...
WHERE NOT pub_date > '2005-1-3'
AND NOT headline = 'Hello'
2つ目の例の方が、制約がより強いことに留意してください。
より複雑なクエリを実行したい場合(たとえば OR ステートメントを含むクエリ)は、 Q オブジェクト (*args) を使用してください。
annotate()¶
- annotate(*args, **kwargs)¶
Annotates each object in the QuerySet with the provided list of query
expressions or Q objects.
Each object can be annotated with:
a simple value, via
Value();a reference to a field on the model (or any related models), via
F();a boolean, via
Q(); ora result from an aggregate expression (averages, sums, etc.) computed over the objects that are related to the objects in the
QuerySet.
annotate() の引数は、それぞれが返り値となる QuerySet 内の各オブジェクトに追加される集計情報となります。
Djangoが提供する集計関数については、下記の Aggregation Functions で説明されています。
キーワード引数を用いて集計情報を定義した場合、キーワードが集計情報のエイリアスとして用いられます。位置引数を用いた場合、使用した集計関数と集計されるモデルフィールドの名前に基づいてエイリアスが生成されます。単一のフィールドを参照する集計式であれば位置引数を利用できます。それ以外のすべての集計式は、キーワード引数を用いなくてはなりません。
たとえば、ブログのリストを操作しているときに、ブログごとのエントリー数を決定したいとします:
>>> from django.db.models import Count
>>> q = Blog.objects.annotate(Count("entry"))
# The name of the first blog
>>> q[0].name
'Blogasaurus'
# The number of entries on the first blog
>>> q[0].entry__count
42
Blog モデル自体は entry__count 属性を定義しませんが、集計式を指定したキーワード引数を用いることで、集計情報の名前を制御できます:
>>> q = Blog.objects.annotate(number_of_entries=Count("entry"))
# The number of entries on the first blog, using the name provided
>>> q[0].number_of_entries
42
集計処理についての深い議論については、 アグリゲーションについてのトピックガイド を確認してください。
alias()¶
- alias(*args, **kwargs)¶
annotate() と同じですが、 QuerySet にオブジェクトをアノテーションするかわりに、後で他の QuerySet メソッドで再利用できるように式を保存します。これは式の結果自体は必要ないが、フィルタリングやソート、あるいは複雑な式の一部として利用する場合に便利です。未使用の値を選択しないことで、データベースで冗長な処理を行わずに済み、結果的にパフォーマンスを向上させることができます。
例えば、5エントリ以上のブログを探したいが、エントリ数自体に興味がない場合は、以下のようにできます:
>>> from django.db.models import Count
>>> blogs = Blog.objects.alias(entries=Count("entry")).filter(entries__gt=5)
alias() は annotate(), exclude(), filter(), order_by(), update() と組み合わせて使用できます。エイリアス式をその他のメソッド(aggregate() など)と組み合わせるためには、アノテーションを用いる必要があります
Blog.objects.alias(entries=Count("entry")).annotate(
entries=F("entries"),
).aggregate(Sum("entries"))
filter() と order_by() は式を直接受け取ることができますが、式の構築と評価は同じ場所では行われないことが多いです(例えば、 QuerySet メソッドは式を作成し、後からビューを表示するときに使用されるため)。 alias() は、複数のメソッドやモジュールにまたがる複雑な式を段階的に構築することができ、式の部分をエイリアスで参照し、最終結果に対してのみ annotate() を使用する、といった使い方ができます。
order_by()¶
- order_by(*fields)¶
デフォルトでは、 QuerySet の返り値はモデルの Meta 内の ordering オプションで指定されたタプルに基づいて並び替えられます。 order_by メソッドを使うことで、 QuerySet ごとにこれをオーバーライドできます。
実装例:
Entry.objects.filter(pub_date__year=2005).order_by("-pub_date", "headline")
上のコードの結果は pub_date の降順、次に headline の昇順で並び替えられます。 "-pub_date" のように、前にマイナス符号をつけることで降順を表現します。昇順は暗黙的に表現されます。ランダムに並び替えたい場合、次のように "?" を使います:
Entry.objects.order_by("?")
メモ: order_by('?') クエリは、使用するデータベースバックエンドによっては高負荷で遅くなる可能性があります。
異なるモデルのフィールドで並び替えたい場合、モデル間を横断して参照するクエリを発行するときと同じ構文を使用します。すなわち、フィールド名の後にダブルアンダースコア(__)を続けて、その後に新たなモデルのフィールド名を続けます。そして、それを結合したいモデルの数だけ繰り返します。例えば:
Entry.objects.order_by("blog__name", "headline")
異なるモデルを参照するフィールドで並び替えるとき、Djangoは参照先のモデルのデフォルトの順序を用いますが、 Meta.ordering が設定されていなければ参照先のモデルのプライマリーキーで並び替えます。たとえば、 Blog モデルにはデフォルトで設定された順序がないとき:
Entry.objects.order_by("blog")
...は以下と同じです:
Entry.objects.order_by("blog__id")
Blog が ordering = ['name'] を保持している場合、最初のクエリセットは以下と同じになります:
Entry.objects.order_by("blog__name")
asc() か desc() を式の中で呼び出すことで、 クエリ式 を使うこともできます:
Entry.objects.order_by(Coalesce("summary", "headline").desc())
asc() と desc() は、null値をどのようにソートするかを制御する引数 (nulls_first と nulls_last)をとります。
モデル参照フィールドによる並び替えと同時に distinct() を使用する際は注意してください。参照先のモデルの順序によって、期待される結果がどのように変化するかについては、 distinct() の注記を確認してください。
注釈
複数の値をとりうるフィールドを指定し、結果を並び替えることは許されています(たとえば、 ManyToManyField フィールド、もしくは ForeignKey フィールドの逆参照など)。
このケースを考えます:
class Event(Model):
parent = models.ForeignKey(
"self",
on_delete=models.CASCADE,
related_name="children",
)
date = models.DateField()
Event.objects.order_by("children__date")
ここで、それぞれの Event に対して、複数の並べ替えデータが存在する可能性があります; 複数の children を伴う Event は、order_by() が作る新たな QuerySet においてそれぞれ複数回返されることになります。言い換えれば、 QuerySet で order_by() を使うことで、もともと作業していたよりも多くの項目を返してしまう可能性があります。これはおそらく予期されることはなく、有用でもないでしょう。
従って、複数の値をとりうるフィールドを結果の並び替えに用いる際は気を付けてください。 もし仮に 並び替える項目ごとに1つのデータしか存在しないのであれば、この方法でも問題はないでしょう。そうでなければ、結果が期待通りになることを確認してください。
大文字と小文字を区別して並べ替えるかどうかを指定することはできません。Djangoは使用するデータベースバックエンドが通常このCase-sensitiveをどのように扱うかに従って結果を並び替えます。
Lower によって小文字に変換したフィールドで並び替えることで、一貫したルールでの並び替えを実現できます:
Entry.objects.order_by(Lower("headline").desc())
クエリに対し、デフォルトの順序付けも含めて並び替えを適用したくない場合、パラメータを指定せずに order_by() を呼び出してください。
クエリに並び替えが適用されたかどうかは、 QuerySet.ordered 属性を確認することで知ることができます。 QuerySet がなんらかの方法で並び替えられれば、この属性の値は True となります。
order_by() の呼び出しごとに、過去の並び替えは解除されます。たとえば、以下のクエリでは並び替えに pub_date が使われ、 headline は使われません:
Entry.objects.order_by("headline").order_by("pub_date")
警告
ソートには計算コストがかかります。ソート条件に追加した各フィールドに、データベースへのコストが発生します。追加する各外部キーには、暗黙的にすべてのデフォルトのソート条件が含まれます。
クエリでソートが指定されていない場合、データベースから返される結果の順序は指定されません。特定の順序が保証されるのは、結果内の各オブジェクトを一意に識別するフィールドの組み合わせでソートした場合だけです。例えば、 name フィールドが一意でない場合、そのフィールドでソートしても、同じ名前のオブジェクトが常に同じ順序で表示されるとは限りません。
reverse()¶
- reverse()¶
reverse() メソッドを使用すると、クエリセットの要素を返す順序を逆にすることができます。再度 reverse() を呼び出すと、順序が元に戻ります。
クエリセットの「最後の」5つの項目を取り出すには、次のようにします:
my_queryset.reverse()[:5]
この処理がPythonでシーケンスの最後からスライスするのとは全く違うことに注意してください。上記の例では、まず最後の項目が返され、次に最後から5番目の項目が返されます。Python のシーケンスに対して seq[-5:] を参照すると、最後の 5 番目の項目が最初に表示されるはずです。そのようなアクセスモード (末尾からのスライス) は、SQL で効率的に行うことができないため、Django ではサポートされていません。
また、通常 reverse() は、順序が定義されている QuerySet に対してしか呼び出せないことに注意してください(例えば、デフォルトの順序を定義しているモデルに対するクエリや、 order_by() を使用する場合など)。 QuerySet に順序が定義されていなかったら、 reverse() を呼び出しても何の効果もありません(順序は reverse() を呼び出す前から未定義であり、その後も未定義のままです)。
distinct()¶
- distinct(*fields)¶
SQL クエリで SELECT DISTINCT を使用した新しい QuerySet を返します。これにより、クエリ結果から重複した行を取り除くことができます。
デフォルトでは、 QuerySet は重複した行を削除しません。なぜなら、 Blog.objects.all() のような単純なクエリでは、結果の行が重複する可能性はないからです。しかし、クエリが複数のテーブルにまたがっている場合、 QuerySet が評価されたときに重複した結果を得る可能性があります。このような場合は distinct() を使用します。
注釈
order_by() の呼び出しで使用されるフィールドはすべて、SQL の SELECT 列に含まれます。これは distinct() と組み合わせて使用すると、時に予期せぬ結果をもたらすことがあります。リレーション先モデルのフィールドでソートした場合、それらのフィールドが SELECT の対象に追加され、重複した行が重複していないように出力されるかもしれません。余分なカラムは返される結果には現れないので (カラムは順序付けをサポートするためだけに存在するため)、重複した結果が返されているように見えることがあります。
同様に、 values() クエリを使用して選択するカラムを制限した場合、 order_by() (またはデフォルトのモデルの順序付け)で使用したカラムが残存し、結果の一意性に影響する可能性があります。
この問題の解決策は、 distinct() を使用する場合、リレーション先のモデルによるソートに注意することです。同様に、 distinct() と values() を一緒に使う場合、 values() の呼び出しに含まれないフィールドによるソートに注意する必要があります。
PostgreSQL のみ、位置引数 (*fields) を渡して、 DISTINCT を適用するフィールドの名前を指定できます。これは SELECT DISTINCT ON というSQLクエリに相当します。通常の distinct() 呼び出しでは、データベースはどの行が区別されるかを判断する際に、各行の each フィールドを比較しますが、フィールド名を指定した distinct() の呼び出しでは、データベースは指定されたフィールド名のみを比較できます。
注釈
フィールド名を指定する場合、QuerySet に order_by() を指定する必要があり、 order_by() のフィールドは distinct() のフィールドと同じ順序で始まる必要があります。
例えば、SELECT DISTINCT ON (a) とすると、列 a の各値の最初の行が得られます。もし順序を指定しなければ、任意の行を得ることができます。
例 (2つ目以降のコードは、PostgreSQL上でのみ動作します):
>>> Author.objects.distinct()
[...]
>>> Entry.objects.order_by("pub_date").distinct("pub_date")
[...]
>>> Entry.objects.order_by("blog").distinct("blog")
[...]
>>> Entry.objects.order_by("author", "pub_date").distinct("author", "pub_date")
[...]
>>> Entry.objects.order_by("blog__name", "mod_date").distinct("blog__name", "mod_date")
[...]
>>> Entry.objects.order_by("author", "pub_date").distinct("author")
[...]
注釈
order_by() はデフォルトで定義されているリレーション先モデルのソートを使用することに注意してください。 ORDER BY 句の先頭にある DISTINCT ON 式が一致するように、明示的に _id やフィールド参照によるソートをする必要があるかもしれません。例えば、 Blog モデルが name による ordering を定義していた場合、:
Entry.objects.order_by("blog").distinct("blog")
このコードは、クエリが blog__name によってソートされるため DISTINCT ON 式と食い違ってしまい、正しい結果を得られないでしょう。2つの式が一致するように、リレーションの _id フィールド(この場合は blog_id )またはフィールド参照( blog__pk )によって明示的にソートする必要があります。
values()¶
- values(*fields, **expressions)¶
イテラブルオブジェクトとして使用するとき、モデルインスタンスではなく辞書を返す QuerySet を返します。
これらの辞書はそれぞれオブジェクトを表し、キーはモデルオブジェクトの属性名に対応しています。
この例では、values() によって得られる辞書と通常のモデルのオブジェクトを比較しています:
# This list contains a Blog object.
>>> Blog.objects.filter(name__startswith="Beatles")
<QuerySet [<Blog: Beatles Blog>]>
# This list contains a dictionary.
>>> Blog.objects.filter(name__startswith="Beatles").values()
<QuerySet [{'id': 1, 'name': 'Beatles Blog', 'tagline': 'All the latest Beatles news.'}]>
values() メソッドはオプションの位置引数 *fields を取り、 SELECT で絞り込むフィールド名を指定します。フィールドを指定した場合、それぞれの辞書は指定したフィールドのキー/値のみを保有します。フィールドを指定しない場合、各辞書は、データベーステーブルのすべてのフィールドのキーと値を保有します。
例:
>>> Blog.objects.values()
<QuerySet [{'id': 1, 'name': 'Beatles Blog', 'tagline': 'All the latest Beatles news.'}]>
>>> Blog.objects.values("id", "name")
<QuerySet [{'id': 1, 'name': 'Beatles Blog'}]>
values() メソッドはオプションでキーワード引数 **expressions を受け取り、 annotate() に渡すこともできます:
>>> from django.db.models.functions import Lower
>>> Blog.objects.values(lower_name=Lower("name"))
<QuerySet [{'lower_name': 'beatles blog'}]>
ソートには、組み込みのルックアップまたは カスタムルックアップ が使用できます。例えば、次のようになります:
>>> from django.db.models import CharField
>>> from django.db.models.functions import Lower
>>> CharField.register_lookup(Lower)
>>> Blog.objects.values("name__lower")
<QuerySet [{'name__lower': 'beatles blog'}]>
values() 句内の集計処理は、同じ values() 句内の他の引数の前に適用されます。別の値でグループ化する必要がある場合は、その値を先の values() 句に追加してください。例えば:
>>> from django.db.models import Count
>>> Blog.objects.values("entry__authors", entries=Count("entry"))
<QuerySet [{'entry__authors': 1, 'entries': 20}, {'entry__authors': 1, 'entries': 13}]>
>>> Blog.objects.values("entry__authors").annotate(entries=Count("entry"))
<QuerySet [{'entry__authors': 1, 'entries': 33}]>
いくつかの際どいポイントについて言及しておきます:
もし
fooというフィールドがForeignKeyである場合、デフォルトのvalues()はfoo_idという辞書キーを返します。それが実際の値を格納するモデルの隠し属性名だからです (foo属性はリレーション先モデルを指します)。value()を呼び出してフィールド名を渡す場合、fooとfoo_idのどちらを渡しても、同じものが返ってきます(辞書のキーは渡したフィールド名と一致します)。例:
>>> Entry.objects.values() <QuerySet [{'blog_id': 1, 'headline': 'First Entry', ...}, ...]> >>> Entry.objects.values("blog") <QuerySet [{'blog': 1}, ...]> >>> Entry.objects.values("blog_id") <QuerySet [{'blog_id': 1}, ...]>
values()とdistinct()を一緒に使う場合、呼び出す順番が結果に影響する場合があるので注意してください。 詳細はdistinct()のノートを参照してください。extra()呼び出しの後にvalues()句を使用する場合、extra()のselect引数で定義したフィールドは、明示的にvalues()呼び出しに含めなければなりません。values()呼び出しの後にextra()を呼び出しても、後から追加した選択フィールドは返り値に含まれません。values()の後にonly()とdefer()を呼び出すのは意味がなく、TypeErrorが発生します。トランスフォームと集計の処理を組み合わせるには、2つの
annotate()呼び出しを、明示的にまたはvalues()へのキーワード引数として使用する必要があります。上記の例のように、リレーション先のフィールドタイプにトランスフォームが登録されていれば、最初のannotate()は省略できます。よって以下の例はすべて等価です:>>> from django.db.models import CharField, Count >>> from django.db.models.functions import Lower >>> CharField.register_lookup(Lower) >>> Blog.objects.values("entry__authors__name__lower").annotate(entries=Count("entry")) <QuerySet [{'entry__authors__name__lower': 'test author', 'entries': 33}]> >>> Blog.objects.values(entry__authors__name__lower=Lower("entry__authors__name")).annotate( ... entries=Count("entry") ... ) <QuerySet [{'entry__authors__name__lower': 'test author', 'entries': 33}]> >>> Blog.objects.annotate(entry__authors__name__lower=Lower("entry__authors__name")).values( ... "entry__authors__name__lower" ... ).annotate(entries=Count("entry")) <QuerySet [{'entry__authors__name__lower': 'test author', 'entries': 33}]>
これは、値が欲しい利用可能フィールドが少なく、モデルインスタンスオブジェクトの機能が必要ないことが分かっている場合に便利です。使用する必要のあるフィールドだけを選択する方がより効率的です。
最後に、values() の後に filter() や order_by() などを呼び出すことができますが、これはこの2つの呼び出しが同じであることを意味しています:
Blog.objects.values().order_by("id")
Blog.objects.order_by("id").values()
Django を作った人たちは、SQL に影響するメソッドを最初に置き、その後に出力に影響するメソッド (values() など) を (オプションで) 置くことを好みますが、それは本当に重要ではありません。しかし、そんなことはどうでもいいのです。この機会に、あなたの個性を存分に発揮してください。
リレーション先モデルのフィールドには、 OneToOneField 、 ForeignKey 、 ManyToManyField 属性を使用して逆リレーションで参照することもできます。
>>> Blog.objects.values("name", "entry__headline")
<QuerySet [{'name': 'My blog', 'entry__headline': 'An entry'},
{'name': 'My blog', 'entry__headline': 'Another entry'}, ...]>
警告
ManyToManyField 属性と逆リレーションは複数の関連行を持つので、これらを含めると結果のサイズが数倍になることがあります。これは、 values() クエリに複数のフィールドを含めると特に顕著で、その場合、考えられるすべての組み合わせが返されることになります。
SQLiteにおける JSONField の特殊な値
SQLiteでは、 JSON_EXTRACT と JSON_TYPE は実装されていますが、 BOOLEAN データ型がないため、 values() は JSONField のキーを変換する際に true, False, None の代わりに "true", "false", "null" の代わりに True, False, None を返します。
values_list()¶
- values_list(*fields, flat=False, named=False)¶
この関数は values() と似ていますが、イテレートしたときに辞書の代わりにタプルを返します。それぞれのタプルには、 values_list() に渡された各フィールドまたは式の値が、渡された順番で含まれます。例えば:
>>> Entry.objects.values_list("id", "headline")
<QuerySet [(1, 'First entry'), ...]>
>>> from django.db.models.functions import Lower
>>> Entry.objects.values_list("id", Lower("headline"))
<QuerySet [(1, 'first entry'), ...]>
フィールドを1つだけ渡す場合は、 flat パラメータを渡すことができます。これに True を渡すと、返り値はタプルではなく単一の値になります。この違いは例を見て理解してください。
>>> Entry.objects.values_list("id").order_by("id")
<QuerySet[(1,), (2,), (3,), ...]>
>>> Entry.objects.values_list("id", flat=True).order_by("id")
<QuerySet [1, 2, 3, ...]>
複数のフィールドがある場合に flat を渡すとエラーになります。
namedtuple(): として結果を得るには、named=True を渡します:
>>> Entry.objects.values_list("id", "headline", named=True)
<QuerySet [Row(id=1, headline='First entry'), ...]>
名前付きタプルを使用することで、名前付きタプルに変換するためのわずかなパフォーマンスの低下を犠牲にして、クエリの実行結果の可読性を高めることができます。
もし values_list() に何も値を渡さなければ、モデル内のすべてのフィールドを宣言された順に返します。
よくあるニーズは、特定のモデルインスタンスの特定のフィールドの値を取得することです。これを実現するには、 values_list() の後に get() を呼び出します:
>>> Entry.objects.values_list("headline", flat=True).get(pk=1)
'First entry'
values() と values_list() はいずれも、モデルインスタンスを作成するオーバーヘッドなしにデータのサブセットを取得するという、特定のユースケースに対する最適化を意図したものです。このメタファーは、多対多の関係やその他の多値の関係(逆引き外部キーの1対多の関係など)を扱うときには、「1行に1オブジェクト」の前提が成り立たないために崩れてしまいます。
例えば、 ManyToManyField: を通してクエリを実行したときの挙動に注目してみましょう:
>>> Author.objects.values_list("name", "entry__headline")
<QuerySet [('Noam Chomsky', 'Impressions of Gaza'),
('George Orwell', 'Why Socialists Do Not Believe in Fun'),
('George Orwell', 'In Defence of English Cooking'),
('Don Quixote', None)]>
複数のエントリを持つ著者は複数回表示され、エントリのない著者のエントリとして None と表示されます。
同様に、外部キーを逆引きするクエリでは、著者が設定されていないエントリに対して None が表示されます。
>>> Entry.objects.values_list("authors")
<QuerySet [('Noam Chomsky',), ('George Orwell',), (None,)]>
SQLiteにおける JSONField の特殊な値
SQLiteでは、 JSON_EXTRACT と JSON_TYPE は実装されていますが、 BOOLEAN データ型がないため、 values_list() は JSONField のキーを変換する際に "true", "false", and "null" の代わりに True, False, None の文字列を返します。
dates()¶
- dates(field, kind, order='ASC')¶
この QuerySet は datetime.date オブジェクトのリストとして評価され、QuerySet の内容から指定された種類の日付を返します。
field にはモデルの DateField の名前を指定します。 kind には "year", "month", "week", "day" のいずれかを指定します。結果のリストに含まれる datetime.date オブジェクトは、指定された type に "切り捨て" られます。
"year"は、そのフィールドのすべての年の値のリストを重複なしで返します。"month"はそのフィールドの年/月の値のリストを重複なしで返します。"week"はそのフィールドの年/週の値のリストを重複なしで返します。すべての date は月曜日になります。"day"はそのフィールドの年/月/日の値のリストを重複なしで返します。
order のデフォルトは 'ASC' で、 'ASC' または 'DESC' のいずれかを指定します。これは結果のソート方法を指定します。
例:
>>> Entry.objects.dates("pub_date", "year")
[datetime.date(2005, 1, 1)]
>>> Entry.objects.dates("pub_date", "month")
[datetime.date(2005, 2, 1), datetime.date(2005, 3, 1)]
>>> Entry.objects.dates("pub_date", "week")
[datetime.date(2005, 2, 14), datetime.date(2005, 3, 14)]
>>> Entry.objects.dates("pub_date", "day")
[datetime.date(2005, 2, 20), datetime.date(2005, 3, 20)]
>>> Entry.objects.dates("pub_date", "day", order="DESC")
[datetime.date(2005, 3, 20), datetime.date(2005, 2, 20)]
>>> Entry.objects.filter(headline__contains="Lennon").dates("pub_date", "day")
[datetime.date(2005, 3, 20)]
datetimes()¶
- datetimes(field_name, kind, order='ASC', tzinfo=None)¶
これは、QuerySet 内の指定した種類の有効な日付を表す datetime.datetime オブジェクトのリストとして評価される QuerySet を返します。
field_name にはモデルの DateTimeField の名前を指定します。
kind には "year", "month", "week", "day", "hour", "minute", "second" のいずれかを指定します。結果のリストに含まれる datetime.datetime オブジェクトは、指定された type に " 切り捨て" られます。
order のデフォルトは 'ASC' で、 'ASC' または 'DESC' のいずれかを指定します。これは結果のソート方法を指定します。
tzinfo は、日時が切り捨てられる前に変換されるタイムゾーンを定義します。実際、与えられた日時は使用されるタイムゾーンによって異なる表現を持ちます。このパラメータは datetime.tzinfo オブジェクトでなければなりません。None の場合、Djangoは カレントタイムゾーン を使用します。USE_TZ が False の場合には効果がありません。
注釈
この関数はデータベース内で直接タイムゾーンの変換を行います。そのため、データベースは tzinfo.tzname(None) の値を解釈できなければなりません。これは以下の要件になります:
SQLite: 要件はありません。変換はPythonで行われます。
PostgreSQL: 要件はありません( Time Zones を参照)。
Oracle: 要件はありません( Choosing a Time Zone File を参照)。
MySQL: mysql_tzinfo_to_sql でタイムゾーンテーブルをロードすること。
none()¶
- none()¶
none() を呼び出すと、オブジェクトを返さないクエリセットが作成され、結果にアクセスする際にクエリが実行されることはありません。 qs.none() のクエリセットは EmptyQuerySet のインスタンスです。
例:
>>> Entry.objects.none()
<QuerySet []>
>>> from django.db.models.query import EmptyQuerySet
>>> isinstance(Entry.objects.none(), EmptyQuerySet)
True
all()¶
- all()¶
現在の QuerySet (または QuerySet サブクラス)の コピー を返します。これは、モデルマネージャまたは QuerySet のどちらかを渡して、その結果に対してさらにフィルタリングを行いたいときに便利です。いずれかのオブジェクトに対して all() を呼び出すと、動作する QuerySet が必ず作成されます。
QuerySet が 評価される とき、通常その結果はキャッシュされます。もし QuerySet が評価された後にデータベースのデータが更新された場合、以前に評価された QuerySet に対して all() を呼び出すことで、同じクエリの最新の結果を取得できます。
union()¶
- union(*other_qs, all=False)¶
SQLの UNION コマンドを使用して、2つ以上の QuerySet の結果を結合します。例えば:
>>> qs1.union(qs2, qs3)
UNION 演算子は、デフォルトでは明確な値のみを選択します。重複した値を取得するには、 all=True 引数を使用します。
union(), intersection(), difference() は、引数が他のモデルの QuerySet であっても、最初の QuerySet の型のモデルインスタンスを返します。すべての QuerySet で SELECT リストが同じであれば、異なるモデルを渡すことができます(少なくとも型と、型の順番が同じであれば名前は関係ありません)。 このような場合、結果の QuerySet に適用される QuerySet メソッドでは、最初の QuerySet のカラム名を使用する必要があります。たとえば、次のようになります:
>>> qs1 = Author.objects.values_list("name")
>>> qs2 = Entry.objects.values_list("headline")
>>> qs1.union(qs2).order_by("name")
結果として得られる QuerySet では、LIMIT、OFFSET、COUNT(*)、ORDER BY、およびカラムの指定(すなわち、スライス、 count() 、 exists() 、 order_by() 、 values() / values_list() )のみが許可されます。さらに、データベースによっては、組み合わせたクエリで許可される操作に制限があります。例えば、ほとんどのデータベースでは組み合わせたクエリで「LIMIT」や「OFFSET」は許可されていません。
intersection()¶
- intersection(*other_qs)¶
SQL の INTERSECT 演算子を使用して、2つ以上の QuerySet の全てに含まれる共有要素を返します。例:
>>> qs1.intersection(qs2, qs3)
制限については union() を参照してください。
difference()¶
- difference(*other_qs)¶
SQL の EXCEPT 演算子を使用して、 QuerySet には存在するが、他の QuerySet には存在しない要素のみを保持します。例:
>>> qs1.difference(qs2, qs3)
制限については union() を参照してください。
extra()¶
- extra(select=None, where=None, params=None, tables=None, order_by=None, select_params=None)¶
Django のクエリ構文だけでは、複雑な WHERE 節を簡単に表現できないことがあります。このようなエッジケースのために、 Django は extra() QuerySet 修飾子、つまり QuerySet が生成する SQL に特定の句を注入するフックを提供します。
このやり方は最後の手段として使ってください。
これは古い API で、将来的には非推奨とする予定です。他の QuerySet メソッドでクエリを表現できない場合にのみ使用してください。もしあなたがこのメソッドを必要とするのであれば、私たちが QuerySet APIを拡張して extra() を削除できるように、 QuerySet.extra キーワード とあなたの使用例を添えて チケットを提出 してください (ただしその前に既存のチケットのリストを確認してください)。このメソッドの改善やバグの修正はもう行っていません。
例えば、 extra() を使った下記のコードは:
>>> qs.extra(
... select={"val": "select col from sometable where othercol = %s"},
... select_params=(someparam,),
... )
下記と等価です:
>>> qs.annotate(val=RawSQL("select col from sometable where othercol = %s", (someparam,)))
RawSQL を使う主な利点は、必要に応じて output_field を指定できることです。主な欠点は、生の SQL でクエリセットのテーブルエイリアスを参照すると、Django がそのエイリアスを変更する可能性があることです (たとえば、クエリセットが別のクエリのサブクエリとして使われる場合など)。
警告
extra() を使うときは常に細心の注意を払ってください。SQL インジェクション攻撃から守るために、使うときは常に params を使用して、ユーザが制御できるパラメータをエスケープする必要があります。
また、SQL文字列のプレースホルダを引用符で囲んではいけません。この例では %s を引用符で囲んでいるため、SQLインジェクションに対して脆弱です:
SELECT col FROM sometable WHERE othercol = '%s' # unsafe!
Django が SQL インジェクションを防ぐ 仕組みの説明があります。
定義上、これらの extra ルックアップは異なるデータベースエンジンに移植できない可能性があり(明示的にSQLコードを記述しているため)、DRY原則に違反するため、可能であれば避けるべきです。
params、select、where、tables のうち、少なくとも1つを指定します。どの引数も必須ではありませんが、少なくとも1つは指定する必要があります。
selectselect引数を使用すると、SELECT句に追加のフィールドを配置できます。属性名を SQL 句にマッピングした辞書を使用して、その属性を計算するために使用します。実装例:
Entry.objects.extra(select={"is_recent": "pub_date > '2006-01-01'"})
その結果、各
Entryオブジェクトには、追加の属性であるis_recentが付与されます。これは、エントリーのpub_dateが2006年1月1日よりも後の日付であるかどうかを表す真偽値です。Django は指定された SQL スニペットを
SELECT文に直接挿入するので、上の例の SQL は次のようになります:SELECT blog_entry.*, (pub_date > '2006-01-01') AS is_recent FROM blog_entry;
次の例はもっと高度です。サブクエリを使って、各結果の
Blogオブジェクトに、関連するEntryオブジェクトの整数カウントであるentry_count属性を付与します。Blog.objects.extra( select={ "entry_count": "SELECT COUNT(*) FROM blog_entry WHERE blog_entry.blog_id = blog_blog.id" }, )
この特別なケースでは、クエリの
FROM句に既にblog_blogテーブルが含まれていることを利用している。上記の例の結果として得られる SQL は次のとおりです:
SELECT blog_blog.*, (SELECT COUNT(*) FROM blog_entry WHERE blog_entry.blog_id = blog_blog.id) AS entry_count FROM blog_blog;
ほとんどのデータベースエンジンでサブクエリに必要な括弧は、Django の
select句では必要ありません。まれに、
extra(select=...)でSQLフラグメントにパラメータを渡したい場合があります。その場合は、select_paramsパラメータを使用してください。これは、次のように動作します:
Blog.objects.extra( select={"a": "%s", "b": "%s"}, select_params=("one", "two"), )
select 文内で文字列
%sをそのまま使いたい場合は、%%sというシーケンスを使用してください。where/tablesSQLの明示的な
WHERE句を定義できます。たとえば、明示的でない結合を実行するためにwhereを使用できます。また、SQLのFROM句に手動でテーブルを追加できます。これにはtablesを使用します。whereとtablesは、どちらも文字列のリストを取ります。全てのwhereパラメーターは、他の検索条件と "AND" 演算されます。実装例:
Entry.objects.extra(where=["foo='a' OR bar = 'a'", "baz = 'a'"])
...これは大まかに次の SQL に翻訳されます:
SELECT * FROM blog_entry WHERE (foo='a' OR bar='a') AND (baz='a')
すでにクエリで使われているテーブルを指定する場合、
tablesパラメータを使うときには注意してください。テーブルtablesパラメータを使ってテーブルを追加すると、 Django はそのテーブルが既に含まれている場合、そのテーブルをもう一回追加したいと仮定します。この場合、テーブル名にエイリアスが付けられるので、問題が生じます。テーブルが SQL 文の中で複数回出現する場合、データベースが区別できるように、2 回目以降の出現にはエイリアスを使う必要があります。追加のwhereパラメータで追加したテーブルを参照している場合、これはエラーの原因になります。通常は、クエリに既に表示されていない追加のテーブルのみを追加します。しかし、上記の場合が発生した場合は、いくつかの解決策があります。まず、追加のテーブルを含めずに、すでにクエリにあるテーブルを使用できるかどうかを確認してください。それが不可能な場合は、
extra()メソッドをクエリセットの構築の最初に配置して、そのテーブルが最初に使用されるようにします。最後に、すべてが失敗した場合は、生成されたクエリを確認し、where句への追加をエイリアスの利用に書き直します。エイリアスは、同じ方法でクエリセットを構築するたびに同じであるため、エイリアス名は変わらないことを信頼できます。order_byextra()で追加した新しいフィールドやテーブルを使用してクエリセットを並べ替える必要がある場合は、extra()のorder_byパラメータを使用し、文字列のシーケンスを渡します。 これらの文字列は、通常の querysets のorder_by()メソッドのようなモデルフィールド、table_name.column_nameの形式、またはextra()のselectパラメータで指定した列のエイリアスである必要があります。例:
q = Entry.objects.extra(select={"is_recent": "pub_date > '2006-01-01'"}) q = q.extra(order_by=["-is_recent"])
これにより、
is_recentが true であるすべてのアイテムが結果セットの先頭に並べ替えられます (降順ではTrueがFalseよりも先に並びます)。ちなみに、これは
extra()を複数回呼び出しても期待通りに動作する(つまり、毎回新しい制約を追加する)ことを示しています。params上記の
whereパラメータは、標準のPythonデータベース文字列プレースホルダー、'%s'を使用して、データベースエンジンが自動的に引用符で囲むべきパラメータを示すことができます。params引数は、代入される追加のパラメータのリストです。実装例:
Entry.objects.extra(where=["headline=%s"], params=["Lennon"])
常に
paramsを使用し、値を直接whereに埋め込まないでください。なぜならparamsを使用することで、値が特定のバックエンドに応じて正しく引用符で囲まれることが保証されるからです。例えば、引用符は正しくエスケープされます。悪い例:
Entry.objects.extra(where=["headline='Lennon'"])
良い例:
Entry.objects.extra(where=["headline=%s"], params=["Lennon"])
警告
もしあなたが MySQL でクエリを処理する場合は、複数の型を扱う際に MySQL の暗黙的な型変換が予期しない結果をもたらす場合がある事に注意してください。もし文字列型で定義したカラムに対し、数値型の値で問い合わせた場合、MySQL は比較処理を行う前にテーブル上の全ての値の型を数値型に変換します。例えば 'abc'、 'def' といった値が含まれているテーブルに対して WHERE mycolumn=0 という条件での問い合わせを行うと、両方の行がマッチします。これを防ぐため、クエリの値を利用する前に適切な型キャストを行ってください。
defer()¶
- defer(*fields)¶
複雑なデータモデリングの場面では、モデルにはたくさんのフィールドが含まれるかもしれません。その中には、大量のデータを含むフィールド (たとえばテキストフィールド) や、Python オブジェクトに変換するために高コストな処理を必要とするフィールドがあるかもしれません。QuerySet の結果を、最初にデータを取得するときにはまだそのフィールドが必要かどうかわからないような状況で使う場合、まだデータベースからは読み込まないように Django に指示できます。
読み込ませたくないフィールドの名前を defer() に渡すことで、それを実現できます:
Entry.objects.defer("headline", "body")
Defer(遅延読み込み)されたフィールドを持つ QuerySet はモデルインスタンスを返します。それぞれの遅延読み込みフィールドは、そのフィールドにアクセスしたときにデータベースから取得されます (すべての遅延読み込みフィールドを一度に取得するのではなく、1つずつ取得します)。
注釈
遅延読み込みに指定されたフィールドは非同期コードからはこのように遅延ロードすることはできません。代わりに SynchronousOnlyOperation 例外が発生します。もし非同期コードを書いているのであれば、defer() されたフィールドにアクセスしようとしてはいけません。
defer() を複数回呼び出すこともできます。それぞれの呼び出しは新しいフィールドを遅延読み込みリストに追加します:
# Defers both the body and headline fields.
Entry.objects.defer("body").filter(rating=5).defer("headline")
フィールドが遅延読み込みリストに追加される順番は重要ではありません。すでに遅延読み込みに指定されているフィールド名で defer() を呼び出しても意味はありません(フィールドは遅延読み込みに指定されたままです)。
標準的な2重アンダースコア記法を用いてリレーション先のフィールドを区切ることで、(リレーション先のモデルが select_related() によって読み込まれる場合) リレーション先のモデルのフィールドの読み込みを遅延させることもできます:
Blog.objects.select_related().defer("entry__headline", "entry__body")
遅延読み込みフィールドの指定を消去したい場合は、 defer() のパラメータとして None を渡します:
# Load all fields immediately.
my_queryset.defer(None)
モデル内のいくつかのフィールドは、指定しても遅延読み込みされません。プライマリキーの読み込みは決して遅延できません。リレーション先のモデルを取得するために select_related() を使っている場合、最初のモデルからリレーション先のモデルに接続するフィールドの読み込みを遅延すべきではありません。
同様に、 defer() (またはそれに対応する only()) を集計関数の引数を含めて (例えば annotate() の結果を使って) 呼び出しても意味はありません。集計された値は常に結果の QuerySet に取り込まれます。
注釈
defer() メソッド(およびその同類である only() 、以下同様)は高度なユースケースのためのものです。クエリを詳細に分析し、どのような情報が必要かを 正確に 理解し、必要なフィールドを返すこととモデルの全フィールドを返すことの差が大きいと判断した場合の最適化を提供するものです。
高度なユースケースだと思う場合でも、 defer() を使用するのは、 QuerySetのロード時に、余分なフィールドが必要かどうかを判断 できない場合だけ にしてください。データの特定のサブセットを頻繁に読み込んで使うなら、モデルを正規化し、ロードしないデータを別のモデル(とデータベーステーブル)に置くのが最善の選択です。もしカラムを一つのテーブル内に どうしても保持する必要がある 場合は、 Meta.managed = False (managed 属性 のドキュメントを参照) に設定されたモデルを作成し、通常必要なフィールドのみを含めます。これは、通常 defer() を呼び出す場合に使用します。これにより、コードは読み手に対してより明示的になり、わずかに速くなり、Pythonプロセスで消費するメモリも少し減ります。
たとえば、これらのモデルはどちらも同じデータベーステーブルを使用しています:
class CommonlyUsedModel(models.Model):
f1 = models.CharField(max_length=10)
class Meta:
managed = False
db_table = "app_largetable"
class ManagedModel(models.Model):
f1 = models.CharField(max_length=10)
f2 = models.CharField(max_length=10)
class Meta:
db_table = "app_largetable"
# Two equivalent QuerySets:
CommonlyUsedModel.objects.all()
ManagedModel.objects.defer("f2")
非マネージドモデルと多くのフィールドを重複させる必要がある場合、共有フィールドを持つ抽象モデルを作成し、非マネージドモデルとマネージドモデルに抽象モデルを継承させるのが最善でしょう。
only()¶
- only(*fields)¶
only() メソッドは本質的に defer() の逆です。このメソッドに渡されたフィールドのうち、既に遅延読み込みフィールドに指定されていないものだけが、 QuerySet が評価されたときに直ちにロードされます。
ほとんどのフィールドが遅延読み込みされる必要があるようなモデルの場合、only() を使って補完的なフィールドセットを指定すると、よりシンプルなコードになります。
name, age, biography という3つのフィールドを持つモデルがあるとします。次の2つのQuerySetは、どのフィールドが遅延読み込みされるかという点では同じです:
Person.objects.defer("age", "biography")
Person.objects.only("name")
only() を呼び出すと、読み込むフィールドの設定を即座に置き換えます。このメソッドは名前の通り、指定したフィールド だけ を読み込み、残りのフィールドの読み込みを先送りします。その結果、連続して only() を呼び出すと、最後に指定したフィールドだけが考慮されることになります:
# This will defer all fields except the headline.
Entry.objects.only("body", "rating").only("headline")
defer() は段階的に(遅延読み込みリストにフィールドを追加しながら)動作するので、 only() と defer() の呼び出しは組み合わせることができ、ロジカルに動作します:
# Final result is that everything except "headline" is deferred.
Entry.objects.only("headline", "body").defer("body")
# Final result loads headline immediately.
Entry.objects.defer("body").only("headline", "body")
defer() のドキュメントにある注意事項はすべて only() にも当てはまります。 only() は慎重に、そして他のオプションを使い果たした後にだけ使用してください。
only() を使って select_related() で要求したフィールドを省略した場合もエラーになります。 一方、引数なしで only() を呼び出すと、queryset によって取得された全てのフィールド (アノテーションを含む) が返されます。
defer() と同様に、非同期コードからは、まだ読み込まれていないフィールドにアクセスすることはできません。その場合、SynchronousOnlyOperation 例外が発生します。アクセスする可能性のあるすべてのフィールドが only() 呼び出し内に含まれていることを確認してください。
using()¶
- using(alias)¶
このメソッドは、複数のデータベースを使用している場合に QuerySet がどのデータベースに対して評価されるかを制御するためのものです。 このメソッドが受け取る唯一の引数は DATABASES で定義されているデータベースのエイリアスです。
例:
# queries the database with the 'default' alias.
>>> Entry.objects.all()
# queries the database with the 'backup' alias
>>> Entry.objects.using("backup")
select_for_update()¶
- select_for_update(nowait=False, skip_locked=False, of=(), no_key=False)¶
トランザクションが終了するまで行をロックし、サポートされているデータベース上で SELECT ... FOR UPDATE SQL 文を生成する QuerySet を返します。
例:
from django.db import transaction
entries = Entry.objects.select_for_update().filter(author=request.user)
with transaction.atomic():
for entry in entries:
...
クエリセットが評価されるとき(この場合、 for entry in entries )、マッチしたすべてのエントリは、トランザクションブロックが終了するまでロックされます。つまり、他のトランザクションがそれらのエントリを変更したりロックを取得したりするのを防ぐことができます。
通常、他のトランザクションが既に選択行の1つをロックしている場合、ロックが解除されるまでクエリはブロックされます。このような動作が望ましくない場合は、 select_for_update(nowait=True) を呼び出してください。これにより、呼び出しがノンブロッキングになります。競合するロックが既に他のトランザクションによって取得されている場合は、クエリセットが評価される際に DatabaseError が発生します。代わりに select_for_update(skip_locked=True) を使用すれば、ロックされた行を無視することもできます。 nowait と skip_locked は互いに排他的であり、両方のオプションを有効にして select_for_update() を呼び出そうとすると ValueError が発生します。
デフォルトでは、 select_for_update() はクエリによって選択された全ての行をロックします。たとえば、クエリセットのモデルの行に加えて、 select_related() で指定したリレーション先のオブジェクトの行もロックされます。この動作が望ましくない場合は、 select_related() と同じフィールド構文を使って select_for_update(of=(...)) でロックしたいリレーション先のオブジェクトを指定してください。クエリセットのモデルを参照するには 'self' という値を使用します。
親モデルを select_for_update(of=(...)) でロックする
マルチテーブル継承 を使用する際に親モデルをロックしたい場合は、 of 引数に親リンクフィールド (デフォルトでは <parent_model_name>_ptr) を指定する必要があります。たとえば次のようになります:
Restaurant.objects.select_for_update(of=("self", "place_ptr"))
フィールドを指定して select_for_update(of=(...)) を使う
例えば values() を使ってモデルをロックし、選択されたフィールドを指定したい場合、 of 引数で各モデルから少なくとも1つのフィールドを選択する必要があります。フィールドが選択されていないモデルはロックされません。
PostgreSQLの場合のみ、no_key=True を渡すことで、ロックがかかっている間、(たとえば外部キーによって)ロックされた行を参照するだけの行を作成できる、より弱いロックを取得できます。PostgreSQLのドキュメントに row-level lock modes についての詳細があります。
null 可能なリレーションでは select_for_update() は使用できません:
>>> Person.objects.select_related("hometown").select_for_update()
Traceback (most recent call last):
...
django.db.utils.NotSupportedError: FOR UPDATE cannot be applied to the nullable side of an outer join
この制限を回避するために、nullオブジェクトを気にしない場合は除外できます:
>>> Person.objects.select_related("hometown").select_for_update().exclude(hometown=None)
<QuerySet [<Person: ...)>, ...]>
データベースバックエンドの postgresql 、 oracle 、 mysql は select_for_update() をサポートしています。ただし、MariaDB は nowait 引数のみをサポートしており、MariaDB 10.6+ は skip_locked 引数もサポートしています。 no_key 引数は PostgreSQL のみでサポートされています。
nowait=True 、 skip_locked=True 、 no_key=True 、または of を select_for_update() に渡すと、MySQL のようなこれらのオプションをサポートしていないデータベースバックエンドでは NotSupportedError が発生します。これはコードが予期せずブロックされるのを防ぎます。
SELECT ... FOR UPDATE をサポートしているバックエンドで select_for_update() をオートコミットモードでクエリセットを評価すると TransactionManagementError エラーになります。もしこれが許される場合、これはデータを用意に破壊します。たとえばトランザクショ ン外のトランザクションで実行されることを期待するコードを呼び出すことで簡単に破壊が起こります。
SELECT ... FOR UPDATE をサポートしていないバックエンド (SQLite など) で select_for_update() を使用しても意味はありません。 SELECT ... FOR UPDATE はクエリに追加されず、 select_for_update() がオートコミットモードで使用されてもエラーは発生しません。
警告
自動コミットモードでは select_for_update() は通常失敗しますが、 TestCase は自動的に各テストをトランザクションでラップするので、 atomic() ブロックの外でも TestCase の中で select_for_update() を呼び出すと、(おそらく予期せず) TransactionManagementError を発生させずに通過します。正しく select_for_update() をテストするには TransactionTestCase を使うべきです。
一部の式はサポートされていません
PostgreSQL は select_for_update() を Window 式でサポートしていません。
raw()¶
- raw(raw_query, params=(), translations=None, using=None)¶
素の SQL クエリを受け取って実行し、 django.db.models.query.RawQuerySet インスタンスを返します。この RawQuerySet インスタンスは、通常の QuerySet と同様にイテレートすることで、オブジェクトインスタンスを生成できます。
詳細は 素の SQL 文の実行 を参照してください。
警告
raw() は常に新しいクエリをトリガーし、以前のフィルタリングを考慮しません。そのため、通常は Manager から呼び出すか、新しい QuerySet インスタンスから呼び出す必要があります。
新しい QuerySet を返す演算子¶
結合したクエリセットは同じモデルを使用しなければなりません。
AND (&)¶
SQL の AND 演算子を使い、フィルタを連結するのと同じように、2つの QuerySet を結合します。
以下のコードは同等です:
Model.objects.filter(x=1) & Model.objects.filter(y=2)
Model.objects.filter(x=1).filter(y=2)
これらは SQL で言う下記と同等です:
SELECT ... WHERE x=1 AND y=2
OR (|)¶
SQL の OR 演算子を使用して、2つの QuerySet を結合します。
以下のコードは同等です:
Model.objects.filter(x=1) | Model.objects.filter(y=2)
from django.db.models import Q
Model.objects.filter(Q(x=1) | Q(y=2))
これらは SQL で言う下記と同等です:
SELECT ... WHERE x=1 OR y=2
| は可換演算ではないので、(等価ではあるが)異なるクエリが生成される可能性があります。
XOR (^)¶
SQLの XOR 演算子を使用して、2つの QuerySet を結合します。XOR 式は、奇数個の条件が真である行にマッチします。
以下のコードは同等です:
Model.objects.filter(x=1) ^ Model.objects.filter(y=2)
from django.db.models import Q
Model.objects.filter(Q(x=1) ^ Q(y=2))
これらは SQL で言う下記と同等です:
SELECT ... WHERE x=1 XOR y=2
注釈
XOR は MariaDB と MySQL ではネイティブでサポートされています。 他のデータベースでは、 x ^ y ^ .... z は下記と等価な式に変換されます:
(x OR y OR ... OR z) AND
1=MOD(
(CASE WHEN x THEN 1 ELSE 0 END) +
(CASE WHEN y THEN 1 ELSE 0 END) +
...
(CASE WHEN z THEN 1 ELSE 0 END),
2
)
古いバージョンでは、SQL の XOR 演算子をネイティブにサポートしていないデータベースでは、 XOR はただ1つの演算子でマッチする行だけを返していました。 以前の動作は MySQL、MariaDB、Python の動作と一致していませんでした。
QuerySet を返さないメソッド¶
以下の QuerySet メソッドは QuerySet を評価し、 QuerySet 以外のものを返します。
これらのメソッドはキャッシュを使用しません ( キャッシュと QuerySet を参照してください)。むしろ、呼び出されるたびにデータベースにクエリを行います。
これらのメソッドは QuerySet を評価するので、ブロッキング呼び出しとなり、そのため主な(同期)バージョンは非同期コードから呼び出すことはできません。このため、それぞれに対応する非同期バージョンがあり、 a 接頭辞が付いています。例えば、 get(…) の代わりに await aget(…) が使用できます。
これらのメソッドの挙動には、通常その非同期性以外に違いはありませんが、各メソッドの具体的な違いは、それぞれのメソッドの説明のすぐそばに記載されています。
get()¶
- get(*args, **kwargs)¶
- aget(*args, **kwargs)¶
非同期バージョン: aget()
指定されたルックアップパラメータに一致するオブジェクトを返します。これらのパラメータは、 Field lookups で説明されている形式に従うべきです。プライマリキーやユニーク制約のあるフィールドのように、一意性が保証されるルックアップを使うべきです。例えば下記のようにします:
Entry.objects.get(id=1)
Entry.objects.get(Q(blog=blog) & Q(entry_number=1))
クエリセットがすでに1行だけを返すことがわかっている場合、引数なしで get() を使うことでその行のオブジェクトを取得できます。
Entry.objects.filter(pk=1).get()
もし get() がオブジェクトを見つけられなかった場合は、 Model.DoesNotExist 例外が発生します。
Entry.objects.get(id=-999) # raises Entry.DoesNotExist
もし get() が複数のオブジェクトを見つけた場合は、 Model.MultipleObjectsReturned 例外が発生します。
Entry.objects.get(name="A Duplicated Name") # raises Entry.MultipleObjectsReturned
これらの例外クラスはモデルクラスの属性であり、そのモデルに特有のものです。複数のモデルに対する get() 呼び出しでこのような例外を処理したい場合、一般的な基底クラスを使用できます。たとえば下記のように、 django.core.exceptions.ObjectDoesNotExist を使って、複数のモデルからの DoesNotExist 例外をできます:
from django.core.exceptions import ObjectDoesNotExist
try:
blog = Blog.objects.get(id=1)
entry = Entry.objects.get(blog=blog, entry_number=1)
except ObjectDoesNotExist:
print("Either the blog or entry doesn't exist.")
create()¶
- create(**kwargs)¶
- acreate(**kwargs)¶
非同期バージョン: acreate()
1ステップでオブジェクトを作成して保存するための便利なメソッドす。たとえばこのようにします:
p = Person.objects.create(first_name="Bruce", last_name="Springsteen")
そして、:
p = Person(first_name="Bruce", last_name="Springsteen")
p.save(force_insert=True)
これらは同等です。
別の場所で force_insert パラメータについても説明していますが、それは新しいオブジェクトを常に作成するよう強制するものです。普通はこれを気にする必要はありません。しかし、モデルが手動で指定したプライマリキー値を含み、その値が既にデータベースに存在する場合、 create() の呼び出しは IntegrityError で失敗します。これは、プライマリキーは一意である必要があるためです。手動のプライマリキーを使用している場合は、例外処理に備える必要があります。
get_or_create()¶
- get_or_create(defaults=None, **kwargs)¶
- aget_or_create(defaults=None, **kwargs)¶
非同期バージョン: aget_or_create()
与えられた kwargs を持つオブジェクトを検索するための便利なメソッドです (モデルがすべてのフィールドをデフォルトで持っている場合は空でもかまいません)。
(Object, created) のタプルを返します。"Object"は受け取ったものか作られたものです。そして"created"はそのObjectが作られたものかどうかのBooleanです。
これは、リクエストが並列処理されたときに、重複したオブジェクトが生成されるのを防ぐため、また、定型的なコードへのショートカットのためです。たとえば次のような場合、:
try:
obj = Person.objects.get(first_name="John", last_name="Lennon")
except Person.DoesNotExist:
obj = Person(first_name="John", last_name="Lennon", birthday=date(1940, 10, 9))
obj.save()
ここで、同時リクエストにより、同じパラメータで Person を保存しようとする試みが複数回行われる可能性があります。この競合状態を回避するために、上記の例は get_or_create() を使って次のように書き換えることができます:
obj, created = Person.objects.get_or_create(
first_name="John",
last_name="Lennon",
defaults={"birthday": date(1940, 10, 9)},
)
get_or_create() に渡されたキーワード引数(オプションの defaults を除く)は get() 呼び出しで使用されます。オブジェクトが見つかった場合、 get_or_create() はそのオブジェクトと False のタプルを返します。
警告
このメソッドはデータベースがキーワード引数の一意性を強制していると仮定してアトミックに動作します (unique または unique_together を参照してください)。キーワード引数で使用されるフィールドにユニーク制約がない場合、このメソッドを同時に呼び出すと、同じパラメータを持つ複数の行が挿入される可能性があります。
get_or_create() と filter() を連結し、 Q オブジェクト を使用することで、取得するオブジェクトに対してより複雑な条件を指定できます。たとえば次のコードは、Robert と Bob Marley のどちらかが存在すればそれを取得し、そうでなければ後者(Bob Marley)を作成します:
from django.db.models import Q
obj, created = Person.objects.filter(
Q(first_name="Bob") | Q(first_name="Robert"),
).get_or_create(last_name="Marley", defaults={"first_name": "Bob"})
複数のオブジェクトが見つかった場合、 get_or_create() は MultipleObjectsReturned を発生させます。オブジェクトが ** 見つからなかった** 場合、 get_or_create() は新しいオブジェクトをインスタンス化して保存し、新しいオブジェクトと True のタプルを返します。新しいオブジェクトはおおよそ以下のアルゴリズムに従って作成されます:
params = {k: v for k, v in kwargs.items() if "__" not in k}
params.update({k: v() if callable(v) else v for k, v in defaults.items()})
obj = self.model(**params)
obj.save()
英語では、defaults' 以外のキーワード引数で、2重アンダースコア(これはexact以外のルックアップを意味します)を含まないものから始めることを意味します。次に defaults の内容を追加し、必要であればキーを上書きして、その結果をモデルクラスのキーワード引数として使用します。もし defaults に呼び出し可能オブジェクトがあれば、それを評価します。上記のように、これは使用されるアルゴリズムを簡略化したものですが、適切な詳細はすべて含まれています。内部実装では、これよりもさらに多くのエラーチェックが行われ、エッジ条件も処理されます。興味があれば、コードを読んでください。
もし defaults という名前のフィールドがあり、それを get_or_create() で正確にルックアップしたい場合は、次のように 'defaults__exact' を使用します:
Foo.objects.get_or_create(defaults__exact="bar", defaults={"defaults": "baz"})
get_or_create() メソッドは create() と同様のエラー動作をします。オブジェクトを作成する必要があり、そのキーが既にデータベースに存在する場合、 IntegrityError が発生します。
最後に、Djangoビューで``get_or_create()``を使用する際の注意点について説明します。よほどの理由がない限り、 POST リクエスト以外では使用しないようにしてください。 GET リクエストはデータに影響を与えるべきではありません。代わりに、データに副作用がある場合は常に``POST``を使用してください。詳細については、HTTP仕様の 安全なメソッド を参照してください。
警告
ManyToManyField 属性と逆リレーションを通じて get_or_create() を使うことができます。この場合、クエリはリレーションのコンテキスト内で制限されます。一貫して使用しないと、整合性の問題が発生する可能性があります。
下記のモデルでは、:
class Chapter(models.Model):
title = models.CharField(max_length=255, unique=True)
class Book(models.Model):
title = models.CharField(max_length=256)
chapters = models.ManyToManyField(Chapter)
get_or_create() は Book の chapters フィールドを通して使うことができますが、その本のコンテキスト内でしか取得できません:
>>> book = Book.objects.create(title="Ulysses")
>>> book.chapters.get_or_create(title="Telemachus")
(<Chapter: Telemachus>, True)
>>> book.chapters.get_or_create(title="Telemachus")
(<Chapter: Telemachus>, False)
>>> Chapter.objects.create(title="Chapter 1")
<Chapter: Chapter 1>
>>> book.chapters.get_or_create(title="Chapter 1")
# Raises IntegrityError
This is happening because it's trying to get or create "Chapter 1" through the
book "Ulysses", but it can't do either: the relation can't fetch that chapter
because it isn't related to that book, but it can't create it either because
title field should be unique.
update_or_create()¶
- update_or_create(defaults=None, create_defaults=None, **kwargs)¶
- aupdate_or_create(defaults=None, create_defaults=None, **kwargs)¶
非同期バージョン: aupdate_or_create()
与えられた kwargs でオブジェクトを更新し、必要に応じて新しいオブジェクトを作成する便利なメソッドです。 create_defaults と defaults はどちらも (field, value) のペアの辞書です。 create_defaults と defaults の値はどちらも呼び出し可能オブジェクトです。 defaults はオブジェクトを更新する際に使用され、create_defaults はオブジェクトを作成する際に使用されます。もし create_defaults が指定されなかった場合、 defaults が作成操作に使用されます。
(Object, created) のタプルを返します。"Object"は受け取ったものか更新したものです。そして"created"はそのObjectが更新されたものかどうかのBooleanです。
update_or_create メソッドは、与えられた kwargs に基づいてデータベースからオブジェクトを取得しようとします。一致するオブジェクトが見つかった場合、 defaults 辞書に渡されたフィールドを更新します。
これは定型的なコードへのショートカットです。たとえば次のようなものです:
defaults = {"first_name": "Bob"}
create_defaults = {"first_name": "Bob", "birthday": date(1940, 10, 9)}
try:
obj = Person.objects.get(first_name="John", last_name="Lennon")
for key, value in defaults.items():
setattr(obj, key, value)
obj.save()
except Person.DoesNotExist:
new_values = {"first_name": "John", "last_name": "Lennon"}
new_values.update(create_defaults)
obj = Person(**new_values)
obj.save()
モデル内のフィールドの数が増えるにつれて、このパターンはかなり扱いにくくなります。上記の例は、 update_or_create() を使って次のように書き換えることができます:
obj, created = Person.objects.update_or_create(
first_name="John",
last_name="Lennon",
defaults={"first_name": "Bob"},
create_defaults={"first_name": "Bob", "birthday": date(1940, 10, 9)},
)
kwargs で渡された名前がどのように解決されるかについては get_or_create() を参照してください。
上記の get_or_create() で説明したように、このメソッドは、データベースレベルで一意性が強制されていない場合、複数の行が同時に挿入される競合状態に陥りがちです。
get_or_create() や create() と同様に、手動で指定したプライマリキーを使用していて、オブジェクトを作成する必要があるが、そのキーが既にデータベースに存在する場合、 IntegrityError が発生します。
create_defaults 引数が追加されました。
bulk_create()¶
- bulk_create(objs, batch_size=None, ignore_conflicts=False, update_conflicts=False, update_fields=None, unique_fields=None)¶
- abulk_create(objs, batch_size=None, ignore_conflicts=False, update_conflicts=False, update_fields=None, unique_fields=None)¶
非同期バージョン: abulk_create()
このメソッドは、指定されたオブジェクトのリストを効率的な方法でデータベースに挿入し (通常、オブジェクトの数にかかわらずクエリは 1 回だけです)、作成されたオブジェクトを指定された順序でリストとして返します:
>>> objs = Entry.objects.bulk_create(
... [
... Entry(headline="This is a test"),
... Entry(headline="This is only a test"),
... ]
... )
しかし、これにはいくつかの注意点があります:
モデルの
save()メソッドは呼び出されず、pre_saveとpost_saveシグナルは送信されません。マルチテーブル継承の子にあたるモデルでは動作しません。
モデルのプライマリキーが
AutoFieldで、ignore_conflictsが False の場合、プライマリキー属性は特定のデータベース(現在は PostgreSQL、MariaDB、SQLite 3.35+)でのみ取得できます。他のデータベースでは、プライマリキーは設定されません。多対多のリレーションシップでは動作しません。
これは
objsをリストにキャストし、それがジェネレータであればobjsを完全に評価します。このキャストにより、手動でプライマリキーを指定したオブジェクトを最初に挿入できるように、すべてのオブジェクトを検査できます。ジェネレータ全体を一度に評価することなく、オブジェクトを一括して挿入したい場合は、オブジェクトに手動で指定したプライマリキーがない限り、このテクニックを使用できます:from itertools import islice batch_size = 100 objs = (Entry(headline="Test %s" % i) for i in range(1000)) while True: batch = list(islice(objs, batch_size)) if not batch: break Entry.objects.bulk_create(batch, batch_size)
batch_size パラメータは、1回のクエリでいくつのオブジェクトを作成するかを制御します。デフォルトでは、すべてのオブジェクトを 1 回のクエリで作成します。ただし、SQLite ではクエリごとに最大 999 個の変数が使用されます。
これをサポートしているデータベース(Oracleを除くすべてのデータベース)では、 ignore_conflicts パラメータを True に設定すると、一意な値の重複などの制約に違反する行の挿入の失敗を無視するようになります。
これをサポートしているデータベース(Oracleを除くすべてのデータベース)では、 update_conflicts パラメータを True に設定すると、行の挿入が競合して失敗したときに update_fields を更新するようになります。PostgreSQL と SQLite では、 update_fields に加えて、競合する可能性のある unique_fields のリストを指定する必要があります。
パラメータ ignore_conflicts を有効にすると、各モデルのインスタンスにプライマリキーを指定できなくなります(データベースが通常サポートしている場合)。
古いバージョンでは、update_conflicts パラメータを有効にすると、各モデルインスタンスにプライマリキーを指定できませんでした。
警告
MySQL と MariaDB では、 ignore_conflicts パラメータを True に設定すると、重複キー以外の特定の種類のエラーが警告に変わります。Strict モードでも同様です。たとえば、無効な値やnull制約違反などです。詳細は MySQL documentation と MariaDB documentation を参照してください。
bulk_update()¶
- bulk_update(objs, fields, batch_size=None)¶
- abulk_update(objs, fields, batch_size=None)¶
非同期バージョン: abulk_update()
このメソッドは、通常1回のクエリで、指定されたモデルインスタンスの指定されたフィールドを効率的に更新し、更新されたオブジェクトの数を返します:
>>> objs = [
... Entry.objects.create(headline="Entry 1"),
... Entry.objects.create(headline="Entry 2"),
... ]
>>> objs[0].headline = "This is entry 1"
>>> objs[1].headline = "This is entry 2"
>>> Entry.objects.bulk_update(objs, ["headline"])
2
QuerySet.update() は変更を保存するために使用されるので、モデルのリストをイテレートしてそれぞれ save() を呼び出すよりも効率的ですが、いくつかの注意点があります:
モデルのプライマリキーは更新できません。
各モデルの
save()メソッドは呼び出されず、pre_saveとpost_saveシグナルは送信されません。多数の行の多数のカラムを更新する場合、生成されるSQLは非常に大きくなる可能性があります。これを避けるには、適切な
batch_sizeを指定します。マルチテーブル継承の継承元に定義されたフィールドを更新すると、継承元ごとに追加のクエリが発生します。
独立した1つのバッチ内に重複がある場合、そのバッチの最初のインスタンスだけが更新されます。
関数が返す更新されたオブジェクトの数は、渡されたオブジェクトの数より少ない場合があります。これは、渡されたオブジェクトが重複して同じバッチで更新されたり、オブジェクトがデータベースに存在しなくなるような競合状態が発生したりすることが原因です。
batch_size パラメータは、1回のクエリで保存されるオブジェクトの数を制御します。クエリで使用できる変数の数に制限がある SQLite と Oracle を除いて、デフォルトではすべてのオブジェクトを一括で更新します。
count()¶
- count()¶
- acount()¶
非同期バージョン: acount()
QuerySet にマッチするデータベース内のオブジェクトの数を整数で返します。
実装例:
# Returns the total number of entries in the database.
Entry.objects.count()
# Returns the number of entries whose headline contains 'Lennon'
Entry.objects.filter(headline__contains="Lennon").count()
count() 呼び出しは裏で SELECT COUNT(*) を実行するので、すべてのレコードを Python オブジェクトに読み込んで、その結果に対して len() を呼び出すのではなく、常に count() を使うべきです(オブジェクトをメモリに読み込む必要がある場合は別です、その場合は len() の方が高速です)。
もし QuerySet に含まれるアイテムの数が必要で、かつそこからモデルインスタンスを取得する場合 (たとえば、それをイテレートする場合) は、おそらく len(queryset) を使用する方が効率的でしょう。count() のように余分なデータベースクエリが発生することがないからです。
クエリセットがすでに完全に取得されている場合、 count() は余計なデータベースクエリを実行するのではなく、その長さを使用します。
in_bulk()¶
- in_bulk(id_list=None, *, field_name='pk')¶
- ain_bulk(id_list=None, *, field_name='pk')¶
非同期バージョン: ain_bulk()
フィールド値のリスト (id_list) とそれらの値の field_name を受け取り、各値を与えられたフィールド値を持つオブジェクトのインスタンスにマッピングした辞書を返します。 django.core.exceptions.ObjectDoesNotExist 例外が in_bulk によって発生することはありません。つまり、インスタンスにマッチしない id_list 値は無視されます。 id_list が指定されなかった場合、クエリセット内の全てのオブジェクトが返されます。フィールド名 field_name は一意なフィールドか、(distinct() で指定されたフィールドが一つしかない場合は) 区別されたフィールドでなければなりません。デフォルトはプライマリキーです。
例:
>>> Blog.objects.in_bulk([1])
{1: <Blog: Beatles Blog>}
>>> Blog.objects.in_bulk([1, 2])
{1: <Blog: Beatles Blog>, 2: <Blog: Cheddar Talk>}
>>> Blog.objects.in_bulk([])
{}
>>> Blog.objects.in_bulk()
{1: <Blog: Beatles Blog>, 2: <Blog: Cheddar Talk>, 3: <Blog: Django Weblog>}
>>> Blog.objects.in_bulk(["beatles_blog"], field_name="slug")
{'beatles_blog': <Blog: Beatles Blog>}
>>> Blog.objects.distinct("name").in_bulk(field_name="name")
{'Beatles Blog': <Blog: Beatles Blog>, 'Cheddar Talk': <Blog: Cheddar Talk>, 'Django Weblog': <Blog: Django Weblog>}
in_bulk() に空のリストを渡すと、空の辞書が返されます。
iterator()¶
- iterator(chunk_size=None)¶
- aiterator(chunk_size=None)¶
非同期バージョン: aiterator()
( クエリを実行して ) QuerySet を評価し、その結果に対するイテレータ (PEP 234 を参照) を返します。非同期バージョンの aiterator を呼び出した場合は、非同期イテレータ (PEP 492 を参照) を返します。
クエリセット QuerySet は通常、結果を内部的にキャッシュするので、繰り返し評価しても追加のクエリが発生することはありません。一方、 iterator() は QuerySet レベルでのキャッシュを行わずに、結果を直接読み込みます (内部的には、デフォルトのイテレータは iterator() を呼び出し、戻り値をキャッシュします)。一度しかアクセスする必要のない大量のオブジェクトを返す QuerySet では、この方がパフォーマンスが向上し、メモリを大幅に削減できます。
すでに評価された クエリセット に対して iterator() を使用すると、クエリを再度評価することになるので注意してください。
chunk_size が与えられている限り、 iterator() は以前の prefetch_related() の呼び出しと互換性があります。より大きな値を指定すると、より少ないクエリでプリフェッチを行う必要がありますが、その代償としてメモリの使用量が大きくなります。
以前の prefetch_related() 呼び出しによる aiterator() のサポートが追加されました。
データベースによっては(例えばOracleや SQLite )、SQLの IN 句の最大項数が制限されている場合があります。そのため、この制限値以下の値を使用する必要があります。(特に、2つ以上のリレーションにまたがってプリフェッチを行う場合、chunk_size は、プリフェッチされた各リレーションに対して予測される結果の数が制限を下回る程度に小さくする必要があります)。
クエリセットがリレーション先のオブジェクトをプリフェッチしない限り、 chunk_size に何も値を指定しないと、 Django は暗黙のデフォルト値 2000 を使います。
データベースのバックエンドによっては、クエリの結果は一度に読み込まれるか、サーバーサイドのカーソルを使ってデータベースからストリーミングされます。
サーバーサイドカーソルとともに使う¶
Oracle と PostgreSQL はサーバーサイドカーソルを使用して、結果セット全体をメモリに読み込むことなくデータベースから結果をストリームします。
Oracle データベースドライバは常にサーバーサイドカーソルを使用します。
サーバーサイドカーソルでは、chunk_size パラメータはデータベースドライバレベルでキャッシュする結果の数を指定します。より大きなチャンクをフェッチすることで、データベースドライバとデータベース間の往復回数を減らすことができます。
PostgreSQLでは、サーバーサイドカーソルは DISABLE_SERVER_SIDE_CURSORS 設定が False の場合のみ使用されます。トランザクションプーリングモードで構成された接続プーラを使用している場合は トランザクションプールとサーバーサイドカーソル を参照してください。サーバーサイドカーソルが無効な場合、動作はサーバーサイドカーソルをサポートしていないデータベースと同じです。
サーバーサイドカーソルなしで使う¶
MySQL は結果のストリーミングをサポートしていないので、Python データベースドライバは結果セット全体をメモリに読み込みます。結果セットはその後、データベースアダプタによって PEP 249 で定義されている fetchmany() メソッドを使用して Python の行オブジェクトに変換されます。
SQLite は fetchmany() を使用してバッチで結果を取得できますが、SQLite は接続内のクエリ間の分離を提供していないため、イテレートするテーブルに書き込む際には注意が必要です。詳細は QuerySet.iterator() を使用する際の分離の問題 を参照してください。
chunk_size パラメータは Django がデータベースドライバから取得するバッチのサイ ズを制御します。バッチを大きくすると、データベースドライバとの通信のオーバヘッ ドが減りますが、その分メモリ消費量が少し増えます。
クエリセットがリレーション先のオブジェクトをプリフェッチしない限り、 chunk_size に何も値を与えない場合、 Django は暗黙のデフォルト値である 2000 を使うことになります。この値は、 psycopg メーリングリスト で計算された値です:
テキストデータと数値データが混在した10~20列の行を想定すると、2000行で100KB以下のデータを取得することになります。これは、転送される行数と、ループが早期に終了した場合に破棄されるデータとの間の良い妥協点だと思われます。
latest()¶
- latest(*fields)¶
- alatest(*fields)¶
非同期バージョン: alatest()
指定されたフィールドに基づいて、テーブル内の最新のオブジェクトを返します。
この例では、 pub_date フィールドに従って、テーブル内の最新の Entry を返します:
Entry.objects.latest("pub_date")
また、複数のフィールドから最新のものを選択することもできます。たとえば2つのエントリが同じ pub_date を持つ場合に、最も早い expire_date を持つ Entry を下記のように選択できます:
Entry.objects.latest("pub_date", "-expire_date")
'-expire_date' の負の符号は、expire_date を 降順 でソートすることを意味します。 latest() は最後の結果を取得するので、 expire_date が最も古い Entry が選択されます。
モデルの Meta が get_latest_by を指定している場合、 earliest() や latest() の引数を省略できます。 get_latest_by で指定されたフィールドがデフォルトで使用されます。
get() と同様に、 earliest() と latest() は与えられたパラメータを持つオブジェクトが存在しない場合、 DoesNotExist を発生させます。
なお、earliest() と latest() は単に利便性と可読性のために存在しています。
earliest() と latest() は null の日付を持つインスタンスを返すことがあります。
ソートはデータベースに委譲されるため、異なるデータベースを使用している場合、NULL値を許可するフィールドの結果は異なる順序になる可能性があります。たとえば、PostgreSQLとMySQLはnull値をnull値でない値よりも上位にあるかのようにソートしますが、SQLiteはその逆です。
下記のように、null 値をフィルタリングしたいこともあるでしょう:
Entry.objects.filter(pub_date__isnull=False).latest("pub_date")
earliest()¶
- earliest(*fields)¶
- aearliest(*fields)¶
非同期バージョン: aearliest()
向きが変わる以外は latest() のように動作します。
first()¶
- first()¶
- afirst()¶
非同期バージョン: afirst()
クエリセットにマッチする最初のオブジェクトを返します。マッチするオブジェクトがない場合は None を返します。QuerySet にソートが定義されていない場合、クエリセットは自動的にプライマリキーでソートされます。これは order_by() と一緒に使う で説明されているように、アグリゲーション(集計)の結果に影響を与える可能性があります。
実装例:
p = Article.objects.order_by("title", "pub_date").first()
first() は便利なメソッドであることに注意してください。以下のコードサンプルは上記の例と等価です:
try:
p = Article.objects.order_by("title", "pub_date")[0]
except IndexError:
p = None
last()¶
- last()¶
- alast()¶
非同期バージョン: alast()
first() のように動作しますが、クエリセットの最後のオブジェクトを返します。
aggregate()¶
- aggregate(*args, **kwargs)¶
- aaggregate(*args, **kwargs)¶
非同期バージョン: aaggregate()
QuerySet に対して計算された集計値 (平均、合計など) の辞書を返します。 aggregate() の各引数は、返却される辞書に含まれる値を指定します。
Django が提供する集計関数は以下の Aggregation Functions で説明されています。 集計は クエリ式 でもあるので、集計を他の集計や値と組み合わせて複雑な集計を作ることができます。
キーワード引数を使用して指定されたアグリゲーション(集計)は、アノテーションの名前としてキーワードを使用します。 無名の引数には、集計関数の名前と集約されるモデルフィールドに基づいて生成された名前が付けられます。複雑な集計では無名の引数を使用することはできず、エイリアスとしてキーワード引数を指定する必要があります。
たとえば、ブログエントリーを扱う場合、下記のように、ブログエントリーを投稿した著者の数を知りたいことがあるでしょう:
>>> from django.db.models import Count
>>> Blog.objects.aggregate(Count("entry__authors"))
{'entry__authors__count': 16}
キーワード引数を使用して集計関数を指定すると、返される集計値の名前を制御できます:
>>> Blog.objects.aggregate(number_of_authors=Count("entry__authors"))
{'number_of_authors': 16}
集計処理についての深い議論については、 アグリゲーションについてのトピックガイド を確認してください。
exists()¶
- exists()¶
- aexists()¶
非同期バージョン: aexists()
戻り値は QuerySet に結果が含まれていれば True を、含まれていなければ False を返します。これは可能な限りシンプルで高速な方法でクエリを実行しようとしますが、通常の QuerySet クエリとほぼ同じクエリを実行します。
exists() は QuerySet に含まれるオブジェクトの存在に関連する検索、特に大きな QuerySet の検索に便利です。
クエリセットに項目が含まれているかどうかを調べるには、次のようにします:
if some_queryset.exists():
print("There is at least one object in some_queryset")
これは以下のコードより高速です:
if some_queryset:
print("There is at least one object in some_queryset")
...しかしそれほど大きな差はありません(したがって、効果を感じるには大きなクエリセットが必要です)。
さらに、some_queryset がまだ評価されていないが、いずれ評価されることがわかっている場合、some_queryset.exists() を使用すると、結果を取得してから返されたかどうかをチェックする bool(some_queryset) を使用するよりも、全体的な作業量(存在チェックのためのクエリ1回と、後で結果を取得するためのクエリ1回)が増えます。
contains()¶
- contains(obj)¶
- acontains(obj)¶
非同期バージョン: acontains()
QuerySet に obj が含まれていれば True を、含まれていなければ False を返します。これは、可能な限りシンプルで高速な方法でクエリを実行しようとします。
contains() は、特に大きな QuerySet のコンテキストにおいて、 QuerySet 内のオブジェクトの所属関係をチェックするのに便利です。
クエリセットに特定の項目が含まれているかどうかを確認するには、次のようにします:
if some_queryset.contains(obj):
print("Entry contained in queryset")
これは、クエリセット全体を評価し、イテレートする必要がある以下の方法よりも高速です:
if obj in some_queryset:
print("Entry contained in queryset")
exists() と同様に、some_queryset がまだ評価されていないが、いずれ評価されることがわかっている場合、some_queryset.contains(obj) を使用すると、追加のデータベースクエリを行うことになり、通常は全体的なパフォーマンスが低下します。
update()¶
- update(**kwargs)¶
- aupdate(**kwargs)¶
非同期バージョン: aupdate()
指定したフィールドに対して SQL の UPDATE クエリを実行し、マッチした行の数を返します (一部の行が既に新しい値を持っている場合は、更新された行の数と一致しないことがあります)。
たとえば、2010年に公開されたすべてのブログエントリーのコメントをオフにするには、次のようにします:
>>> Entry.objects.filter(pub_date__year=2010).update(comments_on=False)
(これは Entry モデルに pub_date と comments_on フィールドがあると仮定しています)。
複数のフィールドを更新できます。たとえば、以下のコードでは comments_on フィールドと headline フィールドを更新しています:
>>> Entry.objects.filter(pub_date__year=2010).update(
... comments_on=False, headline="This is old"
... )
update() メソッドは即座に適用されます。更新される QuerySet の唯一の制限は、モデルのメインテーブルのカラムのみを更新することができ、リレーション先のモデルのカラムを更新することはできないということです。たとえば、このようなことはできません:
>>> Entry.objects.update(blog__name="foo") # Won't work!
リレーション先のフィールドに基づくフィルタリングは可能です:
>>> Entry.objects.filter(blog__id=1).update(comments_on=True)
スライスが取られたり、それ以外の理由でこれ以上フィルタリングできなくなった QuerySet に対しては update() を呼び出すことはできません。
update() メソッドは、影響を受ける行の数を返します:
>>> Entry.objects.filter(id=64).update(comments_on=True)
1
>>> Entry.objects.filter(slug="nonexistent-slug").update(comments_on=True)
0
>>> Entry.objects.filter(pub_date__year=2010).update(comments_on=False)
132
レコードを更新するだけで、モデルオブジェクトに対して何もする必要がない場合、最も効率的なアプローチは、モデルオブジェクトをメモリに読み込むのではなく、 update() を呼び出すことです。たとえば、次のようにす書く代わりに、:
e = Entry.objects.get(id=10)
e.comments_on = False
e.save()
...次のように書きます:
Entry.objects.filter(id=10).update(comments_on=False)
また、update() を使用することで、オブジェクトを読み込んでから save() を呼び出すまでの短い間にデータベース内で何かが変更されてしまう競合状態を防ぐことができます。
MySQL does not support self-select updates
On MySQL, QuerySet.update() may execute a SELECT followed by an
UPDATE instead of a single UPDATE when filtering on related tables,
which can introduce a race condition if concurrent changes occur between
the queries. To ensure atomicity, consider using transactions or avoiding
such filter conditions on MySQL.
最後に、 update() は SQL レベルで更新を行うので、モデル上の save() メソッドを呼び出したり、 pre_save や post_save シグナル ( Model.save() を呼び出した結果発生するシグナル) を発したりしないことに注意してください。カスタム save() メソッドを持つモデルのレコードを更新したい場合は、次のようにループして save() を呼び出します:
for e in Entry.objects.filter(pub_date__year=2010):
e.comments_on = False
e.save()
ソートされたクエリセット¶
order_by() と update() の連結は MariaDB と MySQL でのみサポートされており、異なるデータベースでは無視されます。これは、一意なフィールドを指定された順序で矛盾なく更新する場合に便利です。たとえば次のようにします:
Entry.objects.order_by("-number").update(number=F("number") + 1)
注釈
order_by() 句がアノテーション、継承されたフィールド、リレーション先のルックアップを含んでいる場合、order_by() 句は無視されます。
delete()¶
- delete()¶
- adelete()¶
非同期バージョン: adelete()
QuerySet 内のすべての行に対して SQL による DELETE クエリを実行し、削除されたオブジェクトの数とオブジェクトの種類ごとの削除数を辞書として返します。
delete() は即座に適用されます。スライスが取られたり、それ以外の理由でこれ以上フィルタリングできなくなった QuerySet に対しては delete() を呼び出すことはできません。
たとえば、特定のブログ内のすべてのエントリを削除するには、:
>>> b = Blog.objects.get(pk=1)
# Delete all the entries belonging to this Blog.
>>> Entry.objects.filter(blog=b).delete()
(4, {'blog.Entry': 2, 'blog.Entry_authors': 2})
デフォルトでは、 Django の ForeignKey は SQL の制約 ON DELETE CASCADE をエミュレートします。つまり、削除されるオブジェクトを指す外部キー を持つオブジェクトは一緒に削除されます。たとえば、次のようになります:
>>> blogs = Blog.objects.all()
# This will delete all Blogs and all of their Entry objects.
>>> blogs.delete()
(5, {'blog.Blog': 1, 'blog.Entry': 2, 'blog.Entry_authors': 2})
このカスケードの動作は、ForeignKey に対する on_delete 属性によってカスタマイズできます。
delete() メソッドは一括削除を行い、モデルの delete() メソッドを呼び出しません。しかし、削除されたオブジェクト (カスケード削除を含む) に対して pre_delete と post_delete シグナルを発行します。
Django はシグナルを送ったり、カスケードを処理したりするために、オブジェクトをメモリにフェッチする必要があります。しかし、カスケードもシグナルもない場合、 Django は高速な経路をとり、メモリにフェッチせずにオブジェクトを削除するかもしれ ません。大きな削除の場合、メモリ使用量を大幅に減らすことができます。クエリの実行量も減ります。
on_delete DO_NOTHING に設定されている外部キーは、削除の際に fast-path を取ることを防ぎません。
オブジェクトの削除で生成されるクエリは、実装の詳細部分であり、変更される可能性があることに注意してください。
as_manager()¶
- classmethod as_manager()¶
QuerySet のメソッドをコピーした Manager のインスタンスを返すクラスメソッドです。詳細は QuerySet のメソッドで、マネージャを生成する を参照してください。
このセクションの他の項目とは異なり、クエリを実行しないため、非同期バージョンがないことに注意してください。
explain()¶
- explain(format=None, **options)¶
- aexplain(format=None, **options)¶
非同期バージョン: aexplain()
QuerySet の実行計画文字列を返します。この実行計画は、使用するインデックスや結合を含め、データベースがどのようにクエリを実行するかの詳細を示します。これらの詳細を知ることで、遅いクエリのパフォーマンスを向上させることができます。
たとえば、PostgreSQLを使う場合:
>>> print(Blog.objects.filter(title="My Blog").explain())
Seq Scan on blog (cost=0.00..35.50 rows=10 width=12)
Filter: (title = 'My Blog'::bpchar)
出力はデータベースによって大きく異なります。
explain() は Oracle を除くすべての組み込みデータベースバックエンドでサポートされています。これは Oracle での実装が一筋縄ではいかないからです。
format パラメータは、データベースのデフォルトの出力形式 (通常はテキストベース) から変更します。PostgreSQLは 'TEXT' 、 'JSON' 、 'YAML' 、 'XML' フォーマットをサポートしています。MariaDB と MySQL は 'TEXT' ( 'TRADITIONAL' とも呼びます) と 'JSON' 形式をサポートしています。MySQL 8.0.16+ では、改良された TREE' フォーマットもサポートしています。これは PostgreSQL の 'TEXT' 出力に似ており、サポートされていればデフォルトで使用されます。
データベースによっては、クエリに関する詳細な情報を返すフラグを受け付けるものがあります。これらのフラグをキーワード引数として渡してください。たとえば、PostgreSQLを使用している場合:
>>> print(Blog.objects.filter(title="My Blog").explain(verbose=True, analyze=True))
Seq Scan on public.blog (cost=0.00..35.50 rows=10 width=12) (actual time=0.004..0.004 rows=10 loops=1)
Output: id, title
Filter: (blog.title = 'My Blog'::bpchar)
Planning time: 0.064 ms
Execution time: 0.058 ms
データベースによっては、フラグによってクエリが実行され、データベースに悪影響を及ぼす可能性があります。たとえば、MariaDB、MySQL 8.0.18+、PostgreSQLでサポートされている ANALYZE フラグは、 SELECT クエリであっても、トリガがある場合や関数が呼び出された場合にデータを変更してしまう可能性があります。
PostgreSQL 16 以降で generic_plan オプションのサポートが追加されました。
Field ルックアップ¶
フィールドルックアップは SQL の WHERE 句の内容を指定する方法です。これらは filter() 、 exclude() 、 get() メソッドのキーワード引数として指定します。
概要については モデルとデータベースクエリのドキュメント を参照してください。
Django の組み込みルックアップを以下に示します。モデルフィールドのために カスタムルックアップ を書くこともできます。
利便性のために、ルックアップタイプが指定されていない場合( Entry.objects.get(id=14) のように)、ルックアップタイプは exact とみなされます。
exact¶
完全一致。比較に指定された値が None の場合、SQL の NULL と解釈されます (詳細は isnull を参照してください)。
例:
Entry.objects.get(id__exact=14)
Entry.objects.get(id__exact=None)
これは下記のSQL文と等価です。
SELECT ... WHERE id = 14;
SELECT ... WHERE id IS NULL;
MySQL における比較
MySQL では、データベースのテーブルの「照合順序」の設定で、exact 比較が大文字小文字を区別するかどうかを決めます。これはデータベースの設定で、 Django の設定ではありません。大文字小文字を区別して比較するように MySQL のテーブルを設定することは可能ですが、いくつかの トレードオフが伴います。これについては データベース ドキュメントの 照合順序のセクション を参照してください。
iexact¶
大文字小文字を区別しない完全一致。比較に指定された値が None の場合、SQL の NULL と解釈されます (詳細は isnull を参照してください)。
実装例:
Blog.objects.get(name__iexact="beatles blog")
Blog.objects.get(name__iexact=None)
これは下記のSQL文と等価です。
SELECT ... WHERE name ILIKE 'beatles blog';
SELECT ... WHERE name IS NULL;
最初のクエリは 'Beatles Blog', 'beatles blog', 'BeAtLes BLoG' などにマッチすることに注意してください。
SQLite ユーザーの場合
SQLite バックエンドで非 ASCII 文字列を使用する場合は、文字列の比較に関する データベースのノート に注意してください。SQLiteは非ASCII文字列に対して大文字小文字を区別しないマッチングを行いません。
contains¶
大文字小文字を区別し、文字列を含むかをチェックします。
実装例:
Entry.objects.get(headline__contains="Lennon")
これらは SQL で言う下記と同等です:
SELECT ... WHERE headline LIKE '%Lennon%';
'Lennon honored today' という見出しにはマッチしますが、 'lennon honored today' という見出しにはマッチしないことに注意してください。
SQLite ユーザーの場合
SQLite は大文字小文字を区別する LIKE ステートメントをサポートしていません。詳細は データベースに関する注意事項 を参照してください。
icontains¶
大文字小文字を区別せずに文字列を含むかをチェックします。
実装例:
Entry.objects.get(headline__icontains="Lennon")
これらは SQL で言う下記と同等です:
SELECT ... WHERE headline ILIKE '%Lennon%';
SQLite ユーザーの場合
SQLite バックエンドで非 ASCII 文字列を使用する場合は、文字列の比較に関する データベースに関する注意事項 に注意してください。
in¶
指定されたイテラブル(多くの場合、リスト、タプル、クエリセット)内に含まれるかをチェックします。あまり使われませんが、(イテラブルである)文字列は使用可能です。
例:
Entry.objects.filter(id__in=[1, 3, 4])
Entry.objects.filter(headline__in="abc")
これは下記のSQL文と等価です。
SELECT ... WHERE id IN (1, 3, 4);
SELECT ... WHERE headline IN ('a', 'b', 'c');
リテラル値のリストを提供する代わりに、クエリセットを使用して以下のように値のリストを動的に評価することもできます:
inner_qs = Blog.objects.filter(name__contains="Cheddar")
entries = Entry.objects.filter(blog__in=inner_qs)
このクエリセットは下記のようなサブクエリ内の SELECT 文として評価されます:
SELECT ... WHERE blog.id IN (SELECT id FROM ... WHERE NAME LIKE '%Cheddar%')
もし values() や values_list() の結果の クエリセット を __in ルックアップの値として渡す場合は、結果の中の1つのフィールドだけを抽出するようにする必要があります。たとえば、次のようにします(ブログ名でフィルタリングする場合):
inner_qs = Blog.objects.filter(name__contains="Ch").values("name")
entries = Entry.objects.filter(blog__name__in=inner_qs)
下記の例では例外が発生します。内側のクエリは2つのフィールド値を抽出しようとしているからです:
# Bad code! Will raise a TypeError.
inner_qs = Blog.objects.filter(name__contains="Ch").values("name", "id")
entries = Entry.objects.filter(blog__name__in=inner_qs)
パフォーマンスに関する注意事項
ネストされたクエリの使用には注意し、データベースサーバーのパフォーマンス特性を理解しましょう (疑わしい場合はベンチマークを使用しましょう!)。データベースバックエンドによっては、特に MySQL はネストされたクエリをあまり最適化しません。そのような場合は、値のリストを抽出してから 2 番目のクエリに渡すほうが効率的です。つまり、1つのクエリではなく、下記のように2つのクエリを実行するのです。
values = Blog.objects.filter(name__contains="Cheddar").values_list("pk", flat=True)
entries = Entry.objects.filter(blog__in=list(values))
最初のクエリを強制的に実行するために、Blog QuerySet を list() 呼び出しで囲んでいることに注意してください。これがないと、ネストされたクエリが実行されてしまうからです。これは QuerySet は遅延評価される ためです。
gt¶
~~より大きい(greater than)。
実装例:
Entry.objects.filter(id__gt=4)
これらは SQL で言う下記と同等です:
SELECT ... WHERE id > 4;
gte¶
~~以上(greater than or equal to)。
lt¶
~~未満(less than)。
lte¶
~~以下(less than equal to)。
startswith¶
大文字と小文字を区別して、指定された文字列から始まるかどうかをチェックします。
実装例:
Entry.objects.filter(headline__startswith="Lennon")
これらは SQL で言う下記と同等です:
SELECT ... WHERE headline LIKE 'Lennon%';
SQLite は大文字小文字を区別する LIKE 文をサポートしていません。 SQLite では startswith は istartswith のように動作します。
istartswith¶
大文字と小文字を区別せず、指定された文字列から始まるかどうかをチェックします。
実装例:
Entry.objects.filter(headline__istartswith="Lennon")
これらは SQL で言う下記と同等です:
SELECT ... WHERE headline ILIKE 'Lennon%';
SQLite ユーザーの場合
SQLite バックエンドで非 ASCII 文字列を使用する場合は、文字列の比較に関する データベースに関する注意事項 に注意してください。
endswith¶
大文字と小文字を区別して、指定された文字列で終わるかどうかをチェックします。
実装例:
Entry.objects.filter(headline__endswith="Lennon")
これらは SQL で言う下記と同等です:
SELECT ... WHERE headline LIKE '%Lennon';
SQLite ユーザーの場合
SQLite は大文字小文字を区別する LIKE 文をサポートしていません。 endswith は SQLite の iendswith のように動作します。詳しくは データベースに関する注意事項 のドキュメントを参照してください。
iendswith¶
大文字と小文字を区別せず、指定された文字列で終わるかどうかをチェックします。
実装例:
Entry.objects.filter(headline__iendswith="Lennon")
これらは SQL で言う下記と同等です:
SELECT ... WHERE headline ILIKE '%Lennon'
SQLite ユーザーの場合
SQLite バックエンドで非 ASCII 文字列を使用する場合は、文字列の比較に関する データベースに関する注意事項 に注意してください。
range¶
範囲のチェック(~~を含む)。
実装例:
import datetime
start_date = datetime.date(2005, 1, 1)
end_date = datetime.date(2005, 3, 31)
Entry.objects.filter(pub_date__range=(start_date, end_date))
これらは SQL で言う下記と同等です:
SELECT ... WHERE pub_date BETWEEN '2005-01-01' and '2005-03-31';
range は SQL で BETWEEN が使えるところならどこでも使えます。日付、数字、そして文字でも使えます。
警告
日付で DateTimeField をフィルタリングすると、最終日のアイテムは含まれません。もし pub_date が DateTimeField であった場合、上記の式はこのようなSQLになります:
SELECT ... WHERE pub_date BETWEEN '2005-01-01 00:00:00' and '2005-03-31 00:00:00';
一般的に言って、日付と日時を混在させることはできません。
date¶
datetime フィールドの値を date としてキャストします。追加のフィールドルックアップを連結できます。 date 値を取ります。
実装例:
Entry.objects.filter(pub_date__date=datetime.date(2005, 1, 1))
Entry.objects.filter(pub_date__date__gt=datetime.date(2005, 1, 1))
(このルックアップに等価なSQLの例はありません。これは、関連するクエリの実装がデータベースエンジンによって異なるためです)。
USE_TZ が True の場合、フィールドはフィルタリングの前にカレントタイムゾーンに変換されます。これには データベースのタイムゾーン定義 が必要です。
year¶
日付フィールドとdatetimeフィールドにおける、"年" の完全一致。追加のフィールドルックアップを連結できます。年を整数で指定します。
実装例:
Entry.objects.filter(pub_date__year=2005)
Entry.objects.filter(pub_date__year__gte=2005)
これらは SQL で言う下記と同等です:
SELECT ... WHERE pub_date BETWEEN '2005-01-01' AND '2005-12-31';
SELECT ... WHERE pub_date >= '2005-01-01';
(正確なSQL構文はデータベースエンジンによって異なります)。
USE_TZ が True の場合、日付フィールドはフィルタリングの前にカレントタイムゾーンに変換されます。これにはデータベースの タイムゾーン定義 が必要です。
iso_year¶
日付フィールドとdatetimeフィールドにおける、ISO 8601の週番号と年との完全一致。追加のフィールドルックアップを連結できます。年を整数で指定します。
実装例:
Entry.objects.filter(pub_date__iso_year=2005)
Entry.objects.filter(pub_date__iso_year__gte=2005)
(正確なSQL構文はデータベースエンジンによって異なります)。
USE_TZ が True の場合、日付フィールドはフィルタリングの前にカレントタイムゾーンに変換されます。これにはデータベースの タイムゾーン定義 が必要です。
month¶
日付フィールドおよびdatetimeフィールドにおける、"月" の完全一致。追加のフィールドルックアップを連結できます。1 (1月) から 12 (12月) までの整数を指定します。
実装例:
Entry.objects.filter(pub_date__month=12)
Entry.objects.filter(pub_date__month__gte=6)
これらは SQL で言う下記と同等です:
SELECT ... WHERE EXTRACT('month' FROM pub_date) = '12';
SELECT ... WHERE EXTRACT('month' FROM pub_date) >= '6';
(正確なSQL構文はデータベースエンジンによって異なります)。
USE_TZ が True の場合、日付フィールドはフィルタリングの前にカレントタイムゾーンに変換されます。これにはデータベースの タイムゾーン定義 が必要です。
day¶
日付フィールドとdatetimeフィールドにおける、"日" の完全一致。追加のフィールドルックアップを連結できます。日を整数で指定します。
実装例:
Entry.objects.filter(pub_date__day=3)
Entry.objects.filter(pub_date__day__gte=3)
これらは SQL で言う下記と同等です:
SELECT ... WHERE EXTRACT('day' FROM pub_date) = '3';
SELECT ... WHERE EXTRACT('day' FROM pub_date) >= '3';
(正確なSQL構文はデータベースエンジンによって異なります)。
これは、1 月 3 日、7 月 3 日など、pub_date が月の 3 日目のレコードに一致します。
USE_TZ が True の場合、日付フィールドはフィルタリングの前にカレントタイムゾーンに変換されます。これにはデータベースの タイムゾーン定義 が必要です。
week¶
日付フィールドおよびdatetimeフィールドにおける、 ISO-8601 に従った週番号 (1~52または53) を返します。すなわち、週は月曜日から始まり、最初の週にはその年の最初の木曜日が含まれます。
実装例:
Entry.objects.filter(pub_date__week=52)
Entry.objects.filter(pub_date__week__gte=32, pub_date__week__lte=38)
(このルックアップに等価なSQLの例はありません。これは、関連するクエリの実装がデータベースエンジンによって異なるためです)。
USE_TZ が True の場合、日付フィールドはフィルタリングの前にカレントタイムゾーンに変換されます。これにはデータベースの タイムゾーン定義 が必要です。
week_day¶
日付フィールドとdatetimeフィールドにおける "曜日" の一致。追加のフィールドルックアップを連結できます。
1 (日曜日) から 7 (土曜日) までの曜日を表す整数値を指定します。
実装例:
Entry.objects.filter(pub_date__week_day=2)
Entry.objects.filter(pub_date__week_day__gte=2)
(このルックアップに等価なSQLの例はありません。これは、関連するクエリの実装がデータベースエンジンによって異なるためです)。
pub_date が月曜日(週の2日目)のレコードは、月や年に関係なくマッチすることに注意してください。 週の曜日のインデックスは1日目が日曜日、7日目が土曜日です。
USE_TZ が True の場合、日付フィールドはフィルタリングの前にカレントタイムゾーンに変換されます。これにはデータベースの タイムゾーン定義 が必要です。
iso_week_day¶
日付フィールドおよび datetime フィールドにおける、ISO 8601 曜日との完全一致。追加のフィールドルックアップを連結できます。
1(月曜日)から7(日曜日)までの曜日を表す整数値を取ります。
実装例:
Entry.objects.filter(pub_date__iso_week_day=1)
Entry.objects.filter(pub_date__iso_week_day__gte=1)
(このルックアップに等価なSQLの例はありません。これは、関連するクエリの実装がデータベースエンジンによって異なるためです)。
pub_date が月曜日(週の1日目)のレコードは、月や年に関係なくマッチすることに注意してください。週の曜日のインデックスは1日目が月曜日、7日目が日曜日です。
USE_TZ が True の場合、日付フィールドはフィルタリングの前にカレントタイムゾーンに変換されます。これにはデータベースの タイムゾーン定義 が必要です。
quarter¶
日付および datetime フィールドにおける、"四半期" の一致。追加のフィールドルックアップを連結できます。年の四半期を表す 1 から 4 までの整数値を指定します。
第2四半期(4月1日から6月30日まで)のエントリーを検索する例:
Entry.objects.filter(pub_date__quarter=2)
(このルックアップに等価なSQLの例はありません。これは、関連するクエリの実装がデータベースエンジンによって異なるためです)。
USE_TZ が True の場合、日付フィールドはフィルタリングの前にカレントタイムゾーンに変換されます。これにはデータベースの タイムゾーン定義 が必要です。
time¶
datetime フィールドの場合、値を time としてキャストします。追加のフィールドルックアップを連結できます。 datetime.time 値を取ります。
実装例:
Entry.objects.filter(pub_date__time=datetime.time(14, 30))
Entry.objects.filter(pub_date__time__range=(datetime.time(8), datetime.time(17)))
(このルックアップに等価なSQLの例はありません。これは、関連するクエリの実装がデータベースエンジンによって異なるためです)。
USE_TZ が True の場合、フィールドはフィルタリングの前にカレントタイムゾーンに変換されます。これには データベースのタイムゾーン定義 が必要です。
hour¶
datetimeフィールドとtimeフィールドにおける、"時(hour)" の完全一致。追加のフィールドルックアップを連結できます。0 から 23 までの整数を指定します。
実装例:
Event.objects.filter(timestamp__hour=23)
Event.objects.filter(time__hour=5)
Event.objects.filter(timestamp__hour__gte=12)
これらは SQL で言う下記と同等です:
SELECT ... WHERE EXTRACT('hour' FROM timestamp) = '23';
SELECT ... WHERE EXTRACT('hour' FROM time) = '5';
SELECT ... WHERE EXTRACT('hour' FROM timestamp) >= '12';
(正確なSQL構文はデータベースエンジンによって異なります)。
USE_TZ が True の場合、日付フィールドはフィルタリングの前にカレントタイムゾーンに変換されます。これにはデータベースの タイムゾーン定義 が必要です。
minute¶
datetime フィールドと time フィールドにおける、"分" の完全一致。追加のフィールドルックアップを連結できます。0 から 59 までの整数を指定します。
実装例:
Event.objects.filter(timestamp__minute=29)
Event.objects.filter(time__minute=46)
Event.objects.filter(timestamp__minute__gte=29)
これらは SQL で言う下記と同等です:
SELECT ... WHERE EXTRACT('minute' FROM timestamp) = '29';
SELECT ... WHERE EXTRACT('minute' FROM time) = '46';
SELECT ... WHERE EXTRACT('minute' FROM timestamp) >= '29';
(正確なSQL構文はデータベースエンジンによって異なります)。
USE_TZ が True の場合、日付フィールドはフィルタリングの前にカレントタイムゾーンに変換されます。これにはデータベースの タイムゾーン定義 が必要です。
second¶
datetime および time フィールドにおける、"秒" の完全一致。追加のフィールドルックアップを連結できます。0 から 59 までの整数を指定します。
実装例:
Event.objects.filter(timestamp__second=31)
Event.objects.filter(time__second=2)
Event.objects.filter(timestamp__second__gte=31)
これらは SQL で言う下記と同等です:
SELECT ... WHERE EXTRACT('second' FROM timestamp) = '31';
SELECT ... WHERE EXTRACT('second' FROM time) = '2';
SELECT ... WHERE EXTRACT('second' FROM timestamp) >= '31';
(正確なSQL構文はデータベースエンジンによって異なります)。
USE_TZ が True の場合、日付フィールドはフィルタリングの前にカレントタイムゾーンに変換されます。これにはデータベースの タイムゾーン定義 が必要です。
isnull¶
"True" または "False" を受け取り、それぞれ IS NULL と IS NOT NULL の SQL クエリに対応します。
実装例:
Entry.objects.filter(pub_date__isnull=True)
これらは SQL で言う下記と同等です:
SELECT ... WHERE pub_date IS NULL;
regex¶
大文字小文字を区別する正規表現マッチ。
正規表現の構文は、使用するデータベースバックエンドのものです。正規表現のサポートが組み込まれていないSQLiteの場合、この機能は(Pythonの)ユーザー定義REGEXP関数によって提供され、正規表現の構文はPythonの re モジュールのものとなります。
実装例:
Entry.objects.get(title__regex=r"^(An?|The) +")
これは下記のSQL文と等価です。
SELECT ... WHERE title REGEXP BINARY '^(An?|The) +'; -- MySQL
SELECT ... WHERE REGEXP_LIKE(title, '^(An?|The) +', 'c'); -- Oracle
SELECT ... WHERE title ~ '^(An?|The) +'; -- PostgreSQL
SELECT ... WHERE title REGEXP '^(An?|The) +'; -- SQLite
正規表現の構文を渡す際には、生の文字列(例: 'foo' の代わりに r'foo') を使うことを推奨します。
iregex¶
大文字小文字を区別しない正規表現マッチ。
実装例:
Entry.objects.get(title__iregex=r"^(an?|the) +")
これは下記のSQL文と等価です。
SELECT ... WHERE title REGEXP '^(an?|the) +'; -- MySQL
SELECT ... WHERE REGEXP_LIKE(title, '^(an?|the) +', 'i'); -- Oracle
SELECT ... WHERE title ~* '^(an?|the) +'; -- PostgreSQL
SELECT ... WHERE title REGEXP '(?i)^(an?|the) +'; -- SQLite
集計(Aggregation)関数¶
Django は django.db.models モジュールで以下の集計関数を提供しています。これらの集計関数の使い方は アグリゲーション(集計)に関するトピックガイド を参照してください。集計関数の作成方法については Aggregate ドキュメント を参照してください。
警告
SQLite は日付/時刻フィールドの集計をそのままでは扱えません。これは、 SQLite にはネイティブな日付/時刻フィールドが存在せず、Django は現在、テキストフィールドを使っ てこれらの機能をエミュレートしているからです。SQLite で日付/時刻フィールドの集計を使おうとすると、 NotSupportedError が発生します。
空のクエリセットやグループの場合
集計関数は空の クエリセット やグループで使用すると None を返します。たとえば、 Sum 集計関数は、 QuerySet にエントリが含まれていない場合や、空ではない QuerySet に含まれる空のグループに対して、 0 の代わりに None を返します。代わりに別の値を返すには、 default 引数を定義します。 Count は default 引数をサポートしていないため、 QuerySet が空の場合は 0 を返します。
すべての集計に共通するパラメータは以下の通りです:
expressions¶
モデル上のフィールド、フィールドのトランスフォーム、または クエリ式 を参照する文字列です。
output_field¶
戻り値の モデルフィールド を表すオプションの引数です。
注釈
複数のフィールドタイプを組み合わせる場合、Django が output_field を決定できるのは、全てのフィールドタイプが同じ場合だけです。そうでない場合は、 output_field を自分で指定しなければなりません。
filter¶
オプションで、 Q オブジェクト で、集計する行をフィルタリングします。
たとえば 条件付きの集計 や アノテーションのフィルタリング を参照してください。
default¶
オプションの引数で、クエリセット(またはグループ化)にエントリがない場合にデフォルト値として使用する値を指定できます。
**extra¶
集計によって生成されるSQLに追加のコンテキストを提供できるキーワード引数。
Avg¶
- class Avg(expression, output_field=None, distinct=False, filter=None, default=None, **extra)[ソース]¶
指定した式の平均値を返します。これは、別の
output_fieldを指定しない限り、必ず数値となります。デフォルトのエイリアス:
<field>__avg戻り値の型: 入力が
intの場合はfloatを、それ以外の場合は入力フィールドと同じものを、output_fieldを指定した場合はoutput_fieldを返します。クエリセットまたはグループ化が空の場合はdefaultを返します。
- distinct¶
オプションです。
distinct=Trueの場合、Avgは一意な値の平均値を返します。これは SQL のAVG(DISTINCT <field>)と等価です。デフォルト値はFalseです。
Count¶
- class Count(expression, distinct=False, filter=None, **extra)[ソース]¶
指定した式で関連付けられたオブジェクトの数を返します。
Count('*')は SQL のCOUNT(*)式と等価です。デフォルトのエイリアス:
<field>__count戻り値の型:
int
- distinct¶
オプションです。
distinct=Trueの場合、一意なインスタンスのみをカウントします。これは SQL のCOUNT(DISTINCT <field>)と等価です。デフォルト値はFalseです。
注釈
default引数はサポートされていません。
Max¶
Min¶
StdDev¶
- class StdDev(expression, output_field=None, sample=False, filter=None, default=None, **extra)[ソース]¶
指定した式のデータの標準偏差を返します。
デフォルトのエイリアス:
<field>__stddev戻り値の型: 入力が
intの場合はfloatを、それ以外の場合は入力フィールドと同じものを、output_fieldを指定した場合はoutput_fieldを返します。クエリセットまたはグループ化が空の場合はdefaultを返します。
- sample¶
オプションです。デフォルトでは
StdDevは母集団の標準偏差を返します。ただし、sample=Trueの場合は、標本の標準偏差が返されます。
Sum¶
- class Sum(expression, output_field=None, distinct=False, filter=None, default=None, **extra)[ソース]¶
与えられた式のすべての値の合計を計算します。
デフォルトのエイリアス:
<field>__sum戻り値の型: 入力フィールドと同じ、または
output_fieldが指定されている場合はoutput_fieldを返します。クエリセットまたはグループ化が空の場合はdefaultが返されます。
- distinct¶
オプションです。
distinct=Trueの場合、Sumは一意な値の合計を返します。これは SQL のSUM(DISTINCT )と等価です。デフォルト値はFalseです。
Variance¶
- class Variance(expression, output_field=None, sample=False, filter=None, default=None, **extra)[ソース]¶
指定された式のデータの分散を返します。
デフォルトのエイリアス:
<field>__variance戻り値の型: 入力が
intの場合はfloatを、それ以外の場合は入力フィールドと同じものを、output_fieldを指定した場合はoutput_fieldを返します。クエリセットまたはグループ化が空の場合はdefaultを返します。
- sample¶
オプションです。デフォルトでは
Varianceは母分散を返します。ただし、sample=Trueの場合は、標本の分散を返します。