1. ホーム
  2. パイソン

django の QuerySet のプロパティ

2022-03-02 03:01:45

QuerySetsは、構築、フィルタリング、スライス、およびパラメータとして渡すことができますが、いずれもデータベースに対して操作するものではありません。実際にデータベースを操作するのは、クエリを実行するときだけです。

以下のQuerySetの動作により、クエリが実行されます。

ループ(反復) : QuerySetは反復可能であり、オブジェクトを反復しながらデータベース操作を実行する。たとえば、すべてのブログ記事のビッグタイトルを出力する場合。

<テーブル
1
2
for
e 
in
Entry.objects.
all
():
print
(e.headline)

<スパン スライシング(Slicing) : Pythonの配列スライス構文を使って、QuerySetをスライスすることができます。一般に、未照会の QuerySet をスライスすると、別の未照会の QuerySet が返されます (新しい QuerySet は実行されません)。しかし、スライスする際に "step" パラメータを使うと、 Django はデータベース操作を実行し、リストオブジェクトを返します。クエリされた QuerySet をスライスすると、リストオブジェクトも返されます。

シリアライズ/キャッシュ (ピクリング/キャッシュ) : 詳しくはQuerySetsのpicklingを参照してください。このセクションで強調しているのは、クエリ結果をデータベースから読み込むという点です。

repr() . QuerySetのrepr()メソッドを呼び出すと、クエリが実行されます。これはPythonのコマンドラインでは非常に便利で、APIを使えばすぐにクエリの結果を見ることができます。

len() . クエリの実行は、QuerySetのlen()メソッドを呼び出すことで行われます。これは、ご想像のとおり、クエリ結果のリストの長さを返します。

注意:コレクション内の行数を取得したい場合は、QuerySet の len() メソッドを使用しないでください。データベースレベルで SQL の SELECT COUNT(*) を直接使った方が効率的なので、 Django はこのために count() メソッドを提供しています。詳しくは、以下の count() メソッドを参照してください。

リスト() . QuerySetにlist()メソッドを適用すると、クエリが実行されます。たとえば

<テーブル
1
entry_list 
=
list
(Entry.objects.
all
())

一つ注意点があります: この方法を使うと、Django がリストの内容をメモリにロードするため、大量のメモリを消費します。これに対して、 QuerySet のトラバースは、データベースからデータを読み込んで、オブジェクトが使われるときだけコンテンツにロードします。

QuerySetsのピクルス

QuerySet をシリアライズ (pickle) したい場合、Django はまずクエリオブジェクトをメモリにロードしてシリアライズを完了し、オブジェクトを最初に使えるようにします (データベースから直接データを読み込むと時間がかかるので、キャッシュはこれを回避しようとしているのです)。そして、シリアライゼーションはキャッシュの先行作業なので、クエリをキャッ シュする際には、シリアライゼーションの作業が先に行われます。つまり、QuerySetをデシリアライズするとき、最初に起こるのは、データベースから検索するのではなく、メモリからクエリの結果を取得することです。

必要な情報の一部をシリアライズして、後でデータベースから Queryset を再構築できるようにするだけなら、QuerySet のクエリ・プロパティをシリアライズするだけでよいのです。そして、以下のコードを使用して、元の QuerySet (データベースからの読み取りを行わないもの) を再構築します。

<テーブル
1
2
3
4
>>> 
import
pickle
>>> query 
=
pickle.loads(s)     
# Assuming 's' is the pickled string.
>>> qs 
=
MyModel.objects.
all
()
>>> qs.query 
=
query            
# Restore the original 'query'.

クエリプロパティは不透明なオブジェクトです。つまり、その内部構造は公開されません。それでも、このセクションで述べたシリアライズとデシリアライズについては安全で完全にサポートされています。

クエリ API (QuerySet API)

フィルタ(**kwargs)

与えられたフィルタ条件に一致するオブジェクトを含む新しいQuerySetを返します。

これらのフィルタ条件(**kwargs)の詳細は、以下のField lookupsで説明されている。複数の条件は、SQL 文の中で互いに AND の関係を持つ。

exclude(**kwargs)

与えられたフィルタにマッチしないオブジェクトを含む、新しい QuerySet を返します。

これらのフィルタ条件(**kwargs)は、以下のField lookupsでも詳しく説明されています。複数の条件もSQL文ではANDですが、全体ではNOT()の関係になっています。

次の例は、公開日がpub_dateで2005-1-3より遅く、見出しが"Hello"のブログエントリーをすべて除外します。

<テーブル
1
Entry.objects.exclude(pub_date__gt
=
datetime.date(
2005
, 
1
, 
3
), headline
=
'Hello'
)

SQL文では、これと同等です。

<テーブル