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 化/キャッシュ化。 QuerySet を pickle 化する 際に何が行われるかは次節を参照してください。次節において重要なことは、結果がデータベースから読み出されるという点です。
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[ソース]¶
Trueif theQuerySetis ordered — i.e. has anorder_by()clause or a default ordering on the model.Falseotherwise.
- totally_ordered[ソース]¶
- New in Django 6.1.
Returns
Trueif theQuerySetis ordered and the ordering is deterministic. This requires that the ordering includes a field (or set of fields) that is unique and non-nullable.For queries involving a
GROUP BYclause, the model's default ordering is ignored. Ordering specified via.extra(order_by=...)is also ignored.
注釈
QuerySetのqueryパラメータは、特殊なクエリのサブクラスが内部のクエリ状態を再構築できるようにするために存在します。このパラメータの値はクエリの状態の不透明な表現であり、パブリックAPIの一部ではありません。
新しい QuerySets を返すメソッド¶
QuerySet が返す結果の種類や、SQLクエリの実行方法を変更するための、さまざまな QuerySet の改良メソッドをDjangoは提供します。
注釈
これらのメソッドはデータベースクエリを実行しないので、非同期コードで実行しても 安全 であり、非同期処理専用のメソッドは存在しません。
filter()¶
- filter(*args, **kwargs)¶
与えられたルックアップパラメータにマッチする新しい QuerySet を返します。
ルックアップパラメータ (**kwargs) は以下の Field lookups で説明されているフォーマットに従わなければなりません。複数のパラメータは、元となるSQLステートメントでは AND によって結合されます。
If you need to execute more complex queries (for example, queries with OR
statements), you can use 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() オブジェクト. Each object can be
annotated with:
Value()で指定する単純な値。F()で指定するモデル(または関連モデル)のフィールドへの参照。Q()で指定する真偽値(判定式)。QuerySet内のオブジェクトに関連付けられたオブジェクトに対して計算された集約式(平均、合計など)の結果。
annotate() に渡される引数はそれぞれがアノテーションとなって、返される QuerySet 内の各オブジェクトに追加されます。
Djangoが提供する集計関数については、下記の 集計関数 で説明されています。
キーワード引数を使って指定されたアノテーションは、そのキーワードがアノテーションのエイリアスとして使用されます。匿名引数の場合は、集計関数の名前と集計対象のモデルフィールド名に基づいて自動的にエイリアスが生成されます。匿名引数として使用できるのは、単一のフィールドを参照する集計式のみです。それ以外のすべての式はキーワード引数として指定する必要があります。
たとえば、ブログのリストを操作しているときに、ブログごとのエントリー数を決定したいとします:
>>> 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() can be used in conjunction with annotate(), exclude(),
filter(), order_by(), and update(). To use an aliased
expression with other methods (e.g. aggregate()), you must promote it to
an annotation:
Blog.objects.alias(entries=Count("entry")).annotate(
entries=F("entries"),
).aggregate(Sum("entries"))
filter() and order_by() can take expressions directly, but
expression construction and usage often does not happen in the same place (for
example, QuerySet method creates expressions, for later use in views).
alias() allows building complex expressions incrementally (possibly
spanning multiple methods and modules), referring to the expression parts by
their aliases, and only using annotate() for the final result.
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)をとります。
Be cautious when ordering by fields in related models if you are also using
distinct(). See the note in distinct() for an explanation of how
related model ordering can change the expected results.
注釈
複数の値をとりうるフィールドを指定し、結果を並び替えることは許されています(たとえば、 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())
If you don't want any ordering to be applied to a query, not even the default
ordering, call order_by() with no parameters.
クエリに並び替えが適用されたかどうかは、 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 ではサポートされていません。
Also, note that reverse() should generally only be called on a QuerySet
which has a defined ordering (e.g., when querying against a model which defines
a default ordering, or when using order_by()). If no such ordering is
defined for a given QuerySet, calling reverse() on it has no real
effect (the ordering was undefined prior to calling reverse(), and will
remain undefined afterward).
distinct()¶
- distinct(*fields)¶
SQL クエリで SELECT DISTINCT を使用した新しい QuerySet を返します。これにより、クエリ結果から重複した行を取り除くことができます。
デフォルトでは、 QuerySet は重複した行を削除しません。なぜなら、 Blog.objects.all() のような単純なクエリでは、結果の行が重複する可能性はないからです。しかし、クエリが複数のテーブルにまたがっている場合、 QuerySet が評価されたときに重複した結果を得る可能性があります。このような場合は distinct() を使用します。
注釈
order_by() の呼び出しで使用されるフィールドはすべて、SQL の SELECT 列に含まれます。これは distinct() と組み合わせて使用すると、時に予期せぬ結果をもたらすことがあります。リレーション先モデルのフィールドでソートした場合、それらのフィールドが SELECT の対象に追加され、重複した行が重複していないように出力されるかもしれません。余分なカラムは返される結果には現れないので (カラムは順序付けをサポートするためだけに存在するため)、重複した結果が返されているように見えることがあります。
Similarly, if you use a values() query to restrict the columns
selected, the columns used in any order_by() (or default model
ordering) will still be involved and may affect uniqueness of the results.
The moral here is that if you are using distinct() be careful about
ordering by related models. Similarly, when using distinct() and
values() together, be careful when ordering by fields not in the
values() call.
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()
<QuerySet [...]>
>>> Entry.objects.order_by("pub_date").distinct("pub_date")
<QuerySet [...]>
>>> Entry.objects.order_by("blog").distinct("blog")
<QuerySet [...]>
>>> Entry.objects.order_by("author", "pub_date").distinct("author", "pub_date")
<QuerySet [...]>
>>> Entry.objects.order_by("blog__name", "mod_date").distinct("blog__name", "mod_date")
<QuerySet [...]>
>>> Entry.objects.order_by("author", "pub_date").distinct("author")
<QuerySet [...]>
注釈
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}, ...]>
When using
values()together withdistinct(), be aware that ordering can affect the results. See the note indistinct()for details.If you use a
values()clause after anextra()call, any fields defined by aselectargument in theextra()must be explicitly included in thevalues()call. Anyextra()call made after avalues()call will have its extra selected fields ignored.Calling
only()anddefer()aftervalues()doesn't make sense, so doing so will raise aTypeError.トランスフォームと集計の処理を組み合わせるには、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()¶
Returns a copy of the current QuerySet (or QuerySet subclass). This
can be useful in situations where you might want to pass in either a model
manager or a QuerySet and do further filtering on the result. After calling
all() on either object, you'll definitely have a QuerySet to work with.
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")
In addition, only LIMIT, OFFSET, COUNT(*), ORDER BY, and
specifying columns (i.e. slicing, count(), exists(),
order_by(), and values()/values_list()) are allowed
on the resulting QuerySet. Further, databases place restrictions on
what operations are allowed in the combined queries. For example, most
databases don't allow LIMIT or OFFSET in the combined queries.
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() を参照してください。
fetch_mode()¶
- fetch_mode(mode)¶
Returns a QuerySet that sets the given fetch mode for all model instances
created by this QuerySet. The fetch mode controls on-demand loading of
fields when they are accessed, such as for foreign keys and deferred fields.
For example, to use the FETCH_PEERS mode to
batch-load all related objects on first access:
from django.db import models
books = Book.objects.fetch_mode(models.FETCH_PEERS)
See more in the fetch mode topic guide.
extra()¶
- extra(select=None, where=None, params=None, tables=None, order_by=None, select_params=None)¶
Django のクエリ構文だけでは、複雑な WHERE 節を簡単に表現できないことがあります。このようなエッジケースのために、 Django は extra() QuerySet 修飾子、つまり QuerySet が生成する SQL に特定の句を注入するフックを提供します。
このやり方は最後の手段として使ってください。
This is an old API that we aim to deprecate at some point in the future.
Use it only if you cannot express your query using other queryset methods.
If you do need to use it, please file a ticket using the QuerySet.extra
keyword
with your use case (please check the list of existing tickets first) so
that we can enhance the QuerySet API to allow removing extra(). We are
no longer improving or fixing bugs for this method.
例えば、 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つは指定する必要があります。
selectThe
selectargument lets you put extra fields in theSELECTclause. It should be a dictionary mapping attribute names to SQL clauses to use to calculate that attribute.実装例:
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_byIf you need to order the resulting queryset using some of the new fields or tables you have included via
extra()use theorder_byparameter toextra()and pass in a sequence of strings. These strings should either be model fields (as in the normalorder_by()method on querysets), of the formtable_name.column_nameor an alias for a column that you specified in theselectparameter toextra().例:
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() を呼び出しても意味はありません(フィールドは遅延読み込みに指定されたままです)。
You can defer loading of fields in related models (if the related models are
loading via select_related()) by using the standard double-underscore
notation to separate related fields:
Blog.objects.select_related().defer("entry__headline", "entry__body")
遅延読み込みフィールドの指定を消去したい場合は、 defer() のパラメータとして None を渡します:
# Load all fields immediately.
my_queryset.defer(None)
Some fields in a model won't be deferred, even if you ask for them. You can
never defer the loading of the primary key. If you are using
select_related() to retrieve related models, you shouldn't defer the
loading of the field that connects from the primary model to the related
one, doing so will result in an error.
Similarly, calling defer() (or its counterpart only()) including an
argument from an aggregation (e.g. using the result of annotate())
doesn't make sense: doing so will raise an exception. The aggregated values
will always be fetched into the resulting queryset.
注釈
The defer() method (and its cousin, only(), below) are only for
advanced use-cases. They provide an optimization for when you have analyzed
your queries closely and understand exactly what information you need and
have measured that the difference between returning the fields you need and
the full set of fields for the model will be significant.
Even if you think you are in the advanced use-case situation, only use
defer() when you cannot, at queryset load time, determine if you will
need the extra fields or not. If you are frequently loading and using a
particular subset of your data, the best choice you can make is to
normalize your models and put the non-loaded data into a separate model
(and database table). If the columns must stay in the one table for some
reason, create a model with Meta.managed = False (see the
managed documentation) containing just
the fields you normally need to load and use that where you might otherwise
call defer(). This makes your code more explicit to the reader, is
slightly faster and consumes a little less memory in the Python process.
たとえば、これらのモデルはどちらも同じデータベーステーブルを使用しています:
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)¶
This method is for controlling which database the QuerySet will be
evaluated against if you are using more than one database. The only argument
this method takes is the alias of a database, as defined in
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: ...>, ...]>
The postgresql, oracle, and mysql database backends support
select_for_update(). However, MariaDB only supports the nowait and
skip_locked arguments, and MySQL supports the nowait, skip_locked,
and of arguments. The no_key argument is only supported on 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() がオートコミットモードで使用されてもエラーは発生しません。
警告
Although select_for_update() normally fails in autocommit mode, since
TestCase automatically wraps each test in a
transaction, calling select_for_update() in a TestCase even outside
an atomic() block will (perhaps unexpectedly)
pass without raising a TransactionManagementError. To properly test
select_for_update() you should use
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
)
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()
A convenience method for creating an object and saving it all in one step. Thus:
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)},
)
Any keyword arguments passed to get_or_create() — except an optional one
called defaults — will be used in a get() call. If an object is
found, get_or_create() returns a tuple of that object and False.
警告
このメソッドはデータベースがキーワード引数の一意性を強制していると仮定してアトミックに動作します (unique または unique_together を参照してください)。キーワード引数で使用されるフィールドにユニーク制約がない場合、このメソッドを同時に呼び出すと、同じパラメータを持つ複数の行が挿入される可能性があります。
You can specify more complex conditions for the retrieved object by chaining
get_or_create() with filter() and using Q() オブジェクト. For example,
to retrieve Robert or Bob Marley if either exists, and create the latter
otherwise:
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"})
The get_or_create() method has similar error behavior to create()
when you're using manually specified primary keys. If an object needs to be
created and the key already exists in the database, an
IntegrityError will be raised.
最後に、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
これは Book ”Ulysses" を介して "Chapter 1" を取得または作成しようとしているために発生していますが、どちらの操作も失敗します。 "Chapter1" が "Ulysess" に関連付けられていないため取得に失敗します。また、 title フィールドは一意でなくてはならないので、作成にも失敗します。
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 が発生します。
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"),
... ]
... )
しかし、これにはいくつかの注意点があります:
The model's
save()method will not be called, and thepre_saveandpost_savesignals will not be sent.マルチテーブル継承の子にあたるモデルでは動作しません。
If the model's primary key is an
AutoFieldor has adb_defaultvalue, andignore_conflictsisFalse, the primary key attribute can only be retrieved on certain databases (currently PostgreSQL, MariaDB, and SQLite). On other databases, it will not be set.多対多のリレーションシップでは動作しません。
これは
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 および Oracle では、クエリ内のパラメータ数に制限があります。)
これをサポートしているデータベース(Oracleを除くすべてのデータベース)では、 ignore_conflicts パラメータを True に設定すると、一意な値の重複などの制約に違反する行の挿入の失敗を無視するようになります。
これをサポートしているデータベース(Oracleを除くすべてのデータベース)では、 update_conflicts パラメータを True に設定すると、行の挿入が競合して失敗したときに update_fields を更新するようになります。PostgreSQL と SQLite では、 update_fields に加えて、競合する可能性のある unique_fields のリストを指定する必要があります。
パラメータ ignore_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() を呼び出すよりも効率的ですが、いくつかの注意点があります:
モデルの主キーは更新できません。
Each model's
save()method isn't called, and thepre_saveandpost_savesignals aren't sent.多数の行の多数のカラムを更新する場合、生成されるSQLは非常に大きくなる可能性があります。これを避けるには、適切な
batch_sizeを指定します。多数のオブジェクトを更新する場合、
bulk_update()はクエリを実行する前に、すべてのバッチにわたって各オブジェクトに対するWHEN句をあらかじめ準備することに注意してください。この処理は予想以上に多くのメモリを必要とする場合があります。メモリ使用量を削減するには、次のような方法を利用できます:from itertools import islice batch_size = 100 ids_iter = iter(range(1000)) while ids := list(islice(ids_iter, batch_size)): batch = Entry.objects.filter(id__in=ids) for entry in batch: entry.headline = f"Updated headline {entry.pk}" Entry.objects.bulk_update(batch, ["headline"], batch_size=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() に空のリストを渡すと、空の辞書が返されます。
Support for chaining in_bulk() after values() or
values_list() was added.
iterator()¶
- iterator(chunk_size=None)¶
- aiterator(chunk_size=None)¶
非同期バージョン: aiterator()
Evaluates the QuerySet (by performing the query) and returns an
iterator over the results, or an asynchronous
iterator if you call its asynchronous version aiterator.
A QuerySet typically caches its results internally so that repeated
evaluations do not result in additional queries. In contrast, iterator()
will read results directly, without doing any caching at the QuerySet
level. For a QuerySet which returns a large number of objects that you
only need to access once, this can result in better performance and a
significant reduction in memory.
すでに評価された クエリセット に対して iterator() を使用すると、クエリを再度評価することになるので注意してください。
chunk_size が与えられている限り、 iterator() は以前の prefetch_related() の呼び出しと互換性があります。より大きな値を指定すると、より少ないクエリでプリフェッチを行う必要がありますが、その代償としてメモリの使用量が大きくなります。
データベースによっては(例えば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 で指定されたフィールドがデフォルトで使用されます。
Like get(), earliest() and latest() raise
DoesNotExist if there is no object with the
given parameters.
なお、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()
Returns the first object matched by the queryset, or None if there
is no matching object. If the QuerySet has no ordering defined (and has not
had ordering forcibly cleared by calling order_by() with no arguments),
then the queryset is automatically ordered by the primary key. This can affect
aggregation results as described in 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
first() and last() no longer order by the primary key when
ordering has been forcibly cleared by calling order_by() with no
arguments.
last()¶
- last()¶
- alast()¶
非同期バージョン: alast()
Works like first(), but returns the last object in the queryset.
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 は自己を参照した更新処理をサポートしていません
MySQL では、関連テーブルに対してフィルタリングしている場合、 QuerySet.update() において単一の UPDATE ではなく SELECT に続けて UPDATE を実行することがあり、クエリ間で同時変更が発生すると競合状態を引き起こす可能性があります。原子性を確保するには、トランザクションを使用するか、MySQL ではそのようなフィルタ条件を避けることを検討してください。
Finally, realize that update() does an update at the SQL level and, thus,
method does not call any
save() methods on your models, nor does it emit the
pre_save or
post_save signals (which are a consequence of
calling Model.save()). If you want to
update a bunch of records for a model that has a custom
save() method, loop over them and call
save(), like this:
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()
Performs an SQL delete query on all rows in the QuerySet and
returns the number of objects deleted and a dictionary with the number of
deletions per object type. The return value will count instances from related
models if Django is emulating cascade behavior via Python
on_delete variants. Otherwise, for
database variants such as DB_CASCADE, the return
value will report only instances of the QuerySet's model.
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 属性によってカスタマイズできます。
The delete() method does a bulk delete and does not call any delete() methods on your
models. It does, however, emit the pre_delete
and post_delete signals for all deleted
objects (including cascaded deletions). Signals won't be sent when
DB_CASCADE is used. Also, delete() doesn't return information about
objects deleted from database variants (DB_*) of the
on_delete argument, e.g. DB_CASCADE.
Django won’t need to fetch objects into memory when deleting them in the following cases:
If related fields use
DB_*options.If there are no cascades and no delete signal receivers.
In these cases, Django may take a fast path and delete objects without fetching them, which can result in significantly reduced memory usage and fewer executed queries.
on_delete DO_NOTHING に設定されている外部キーは、削除の際に fast-path を取ることを防ぎません。
オブジェクトの削除で生成されるクエリは、実装の詳細部分であり、変更される可能性があることに注意してください。
Support for the DB_* variants of on_delete attribute was added.
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 での実装が一筋縄ではいかないからです。
The format parameter changes the output format from the database's
default, which is usually text-based. PostgreSQL supports 'TEXT',
'JSON', 'YAML', and 'XML' formats. MariaDB and MySQL support
'TEXT' (also called 'TRADITIONAL') and 'JSON' formats. MySQL
8.0.16+ also supports an improved 'TREE' format, which is similar to
PostgreSQL's 'TEXT' output and is used by default, if supported.
データベースによっては、クエリに関する詳細な情報を返すフラグを受け付けるものがあります。これらのフラグをキーワード引数として渡してください。たとえば、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
On some databases, flags may cause the query to be executed which could have
adverse effects on your database. For example, the ANALYZE flag supported
by MariaDB, MySQL, and PostgreSQL could result in changes to data if there are
triggers or if a function is called, even for a SELECT query.
Field ルックアップ¶
Field lookups are how you specify the meat of an SQL WHERE clause. They're
specified as keyword arguments to the QuerySet methods filter(),
exclude() and get().
概要については モデルとデータベースクエリのドキュメント を参照してください。
Django の組み込みルックアップを以下に示します。モデルフィールドのために カスタムルックアップ を書くこともできます。
利便性のために、ルックアップタイプが指定されていない場合( Entry.objects.get(id=14) のように)、ルックアップタイプは exact とみなされます。
exact¶
Exact match. If the value provided for comparison is None, it will be
interpreted as an SQL NULL (see isnull for more details).
Key and index lookups are exceptions: they
interpret None as JSON null instead.
例:
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%';
(正確なSQL構文はデータベースエンジンによって異なります)。
'Lennon honored today' という見出しにはマッチしますが、 'lennon honored today' という見出しにはマッチしないことに注意してください。
SQLite ユーザーの場合
SQLite は大文字小文字を区別する LIKE ステートメントをサポートしていません。詳細は データベースに関する注意事項 を参照してください。
icontains¶
大文字小文字を区別せずに文字列を含むかをチェックします。
実装例:
Entry.objects.get(headline__icontains="Lennon")
これらは SQL で言う下記と同等です:
SELECT ... WHERE headline ILIKE '%Lennon%';
(正確なSQL構文はデータベースエンジンによって異なります)。
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%';
(正確なSQL構文はデータベースエンジンによって異なります)。
SQLite は大文字小文字を区別する LIKE 文をサポートしていません。 SQLite では startswith は istartswith のように動作します。
istartswith¶
大文字と小文字を区別せず、指定された文字列から始まるかどうかをチェックします。
実装例:
Entry.objects.filter(headline__istartswith="Lennon")
これらは SQL で言う下記と同等です:
SELECT ... WHERE headline ILIKE 'Lennon%';
(正確なSQL構文はデータベースエンジンによって異なります)。
SQLite ユーザーの場合
SQLite バックエンドで非 ASCII 文字列を使用する場合は、文字列の比較に関する データベースに関する注意事項 に注意してください。
endswith¶
大文字と小文字を区別して、指定された文字列で終わるかどうかをチェックします。
実装例:
Entry.objects.filter(headline__endswith="Lennon")
これらは SQL で言う下記と同等です:
SELECT ... WHERE headline LIKE '%Lennon';
(正確なSQL構文はデータベースエンジンによって異なります)。
SQLite ユーザーの場合
SQLite は大文字小文字を区別する LIKE 文をサポートしていません。 endswith は SQLite の iendswith のように動作します。詳しくは データベースに関する注意事項 のドキュメントを参照してください。
iendswith¶
大文字と小文字を区別せず、指定された文字列で終わるかどうかをチェックします。
実装例:
Entry.objects.filter(headline__iendswith="Lennon")
これらは SQL で言う下記と同等です:
SELECT ... WHERE headline ILIKE '%Lennon';
(正確なSQL構文はデータベースエンジンによって異なります)。
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¶
An optional Q object that's used to filter the rows that are aggregated.
たとえば 条件付きの集計 や アノテーションのフィルタリング を参照してください。
default¶
オプションの引数で、クエリセット(またはグループ化)にエントリがない場合にデフォルト値として使用する値を指定できます。
**extra¶
集計によって生成されるSQLに追加のコンテキストを提供できるキーワード引数。
AnyValue¶
- class AnyValue(expression, output_field=None, filter=None, default=None, **extra)[ソース]¶
Returns an arbitrary value from the non-null input values.
Default alias:
<field>__anyvalue戻り値の型: 入力フィールドと同じ、または
output_fieldが指定されている場合はoutput_fieldを返します。クエリセットまたはグループ化が空の場合はdefaultが返されます。
使用例:
>>> # Get average rating for each year along with a sample headline >>> # from that year. >>> from django.db.models import AnyValue, Avg, F, Q >>> sample_headline = AnyValue("headline") >>> Entry.objects.values( ... pub_year=F("pub_date__year"), ... ).annotate( ... avg_rating=Avg("rating"), ... sample_headline=sample_headline, ... ) >>> # Get a sample headline from each year with rating greater than 4.5. >>> sample_headline = AnyValue( ... "headline", ... filter=Q(rating__gt=4.5), ... ) >>> Entry.objects.values( ... pub_year=F("pub_date__year"), ... ).annotate( ... avg_rating=Avg("rating"), ... sample_headline=sample_headline, ... )
Supported on SQLite, MySQL, Oracle, and PostgreSQL 16+.
MySQL with
ONLY_FULL_GROUP_BYenabledWhen the
ONLY_FULL_GROUP_BYSQL mode is enabled on MySQL it may be necessary to useAnyValueif an aggregation includes a mix of aggregate and non-aggregate functions. UsingAnyValueallows the non-aggregate function to be referenced in the select list when database cannot determine that it is functionally dependent on the columns in the group by clause. See the aggregation documentation for more details.
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です。
BitAnd¶
BitOr¶
BitXor¶
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の場合は、標本の分散を返します。
StringAgg¶
- class StringAgg(expression, delimiter, output_field=None, distinct=False, filter=None, order_by=None, default=None, **extra)[ソース]¶
入力値を文字列に連結し、
delimiter文字列で区切って返します。値がない場合はdefaultを返します。Default alias:
<field>__stringaggReturn type:
stringoroutput_fieldif supplied. If the queryset or grouping is empty,defaultis returned.
- delimiter¶
A
Valueor expression representing the string that should separate each of the values. For example,Value(","). (On SQLite, the literal delimiterValue(",")is the only delimiter compatible withdistinct=True.)Changed in Django 6.1:Support for using
distinct=Truewith a delimiter ofValue(",")on SQLite was added.