---
title: "クエリを作成する"
version: 5.1
locale: ja
source: https://docs.djangoproject.com/ja/5.1/topics/db/queries/
canonical: https://djangodocs.dev/ja/5.1/topics/db/queries/
---
# クエリを作成する

一度 [データモデル](/ja/5.1/topics/db/models/) を作成すれば、Django はデータオブジェクトの作成、取得、更新および削除を行えるようにデータベースを抽象化した API を自動的に提供します。本ドキュメントではこの API をどのように用いるかを説明します。多様なモデル探索オプション全てに関する詳細については [データモデルの項目](/ja/5.1/ref/models/) を参照ください。

このガイド（およびリファレンス）全体を通して、以下のモデルを参照します。これらはブログアプリケーションを構成するものです。

```python
from datetime import date

from django.db import models

class Blog(models.Model):
    name = models.CharField(max_length=100)
    tagline = models.TextField()

    def __str__(self):
        return self.name

class Author(models.Model):
    name = models.CharField(max_length=200)
    email = models.EmailField()

    def __str__(self):
        return self.name

class Entry(models.Model):
    blog = models.ForeignKey(Blog, on_delete=models.CASCADE)
    headline = models.CharField(max_length=255)
    body_text = models.TextField()
    pub_date = models.DateField()
    mod_date = models.DateField(default=date.today)
    authors = models.ManyToManyField(Author)
    number_of_comments = models.IntegerField(default=0)
    number_of_pingbacks = models.IntegerField(default=0)
    rating = models.IntegerField(default=5)

    def __str__(self):
        return self.headline
```

## オブジェクトを作成する

Djangoでは、データベースのテーブルデータをPythonオブジェクトで表現するために、直感的な仕組みを採用しています。モデルクラスはデータベースのテーブルを表し、そのクラスのインスタンスはデータベーステーブル内の特定のレコードを表します。

オブジェクトを生成するためには、作成するモデルのクラスにキーワード引数を渡してインスタンス化し、そのデータをデータベースに保存するために [`save()`](/ja/5.1/ref/models/instances/#django.db.models.Model.save) を呼び出します。

以下はモデルがDjangoアプリ `blog` 内の `models.py` ファイルに存在する場合の例です。

```pycon
>>> from blog.models import Blog
>>> b = Blog(name="Beatles Blog", tagline="All the latest Beatles news.")
>>> b.save()
```

この例では内部で `INSERT` SQL 文が処理されます。明示的に [`save()`](/ja/5.1/ref/models/instances/#django.db.models.Model.save) を呼ぶまで Django はデータベースを操作しません。

[`save()`](/ja/5.1/ref/models/instances/#django.db.models.Model.save) メソッドは値を返しません。

> **See also**
>
> [`save()`](/ja/5.1/ref/models/instances/#django.db.models.Model.save) はここには記述されていない多数の高度なオプションを持ちます。詳細については [`save()`](/ja/5.1/ref/models/instances/#django.db.models.Model.save) の項目を参照してください。
>
> オブジェクトの作成と保存を一つの処理で行うには、 [`create()`](/ja/5.1/ref/models/querysets/#django.db.models.query.QuerySet.create) メソッドを利用してください。

## オブジェクトに対する変更を保存する

既にデータベース上に存在する 1 つのオブジェクトに対する変更を保存するには、 [`save()`](/ja/5.1/ref/models/instances/#django.db.models.Model.save) を利用します。

すでにデータベースに保存されている `Blog` インスタンス `b5` がある場合、この例ではその名前を変更し、データベース内のレコードを更新します:

```pycon
>>> b5.name = "New name"
>>> b5.save()
```

この例では内部で `UPDATE` SQL 文が処理されます。明示的に [`save()`](/ja/5.1/ref/models/instances/#django.db.models.Model.save) が呼ばれるまで Django はデータベースを操作しません。

### `ForeignKey` と `ManyToManyField` フィールドを扱う

[`ForeignKey`](/ja/5.1/ref/models/fields/#django.db.models.ForeignKey) フィールドを更新するには、通常のフィールドを保存するのと全く同じように、該当のフィールドに適切なタイプのオブジェクトを割り当てます。以下の例では、 `Entry` インスタンス `entry` の `blog` 属性を更新しています。ここでは、 `Entry` と `Blog` の適切なインスタンスが既にデータベースに保存されていると仮定しています（したがって、以下でそれらを取得できます）。

```pycon
>>> from blog.models import Blog, Entry
>>> entry = Entry.objects.get(pk=1)
>>> cheese_blog = Blog.objects.get(name="Cheddar Talk")
>>> entry.blog = cheese_blog
>>> entry.save()
```

[`ManyToManyField`](/ja/5.1/ref/models/fields/#django.db.models.ManyToManyField) を更新する方法は少し異なります。関連するフィールド上の [`add()`](/ja/5.1/ref/models/relations/#django.db.models.fields.related.RelatedManager.add) メソッドを使用して、リレーションにレコードを追加します。以下の例では、 `Author` インスタンス `joe` を `entry` オブジェクトに追加しています:

```pycon
>>> from blog.models import Author
>>> joe = Author.objects.create(name="Joe")
>>> entry.authors.add(joe)
```

複数のレコードを [`ManyToManyField`](/ja/5.1/ref/models/fields/#django.db.models.ManyToManyField) に一気に追加するには、 [`add()`](/ja/5.1/ref/models/relations/#django.db.models.fields.related.RelatedManager.add) の呼び出しに複数の引数を含めてください:

```pycon
>>> john = Author.objects.create(name="John")
>>> paul = Author.objects.create(name="Paul")
>>> george = Author.objects.create(name="George")
>>> ringo = Author.objects.create(name="Ringo")
>>> entry.authors.add(john, paul, george, ringo)
```

もし間違った型のオブジェクトを設定もしくは追加しようとすれば Django はエラーを発生させます。

## オブジェクトを取得する

データベースからオブジェクトを取得するには、モデルクラスの [`Manager`](/ja/5.1/topics/db/managers/#django.db.models.Manager) から [`QuerySet`](/ja/5.1/ref/models/querysets/#django.db.models.query.QuerySet) を作ります。

[`QuerySet`](/ja/5.1/ref/models/querysets/#django.db.models.query.QuerySet) はデータベース上のオブジェクトの集合を表しています。多数の *フィルタ* を持つことができます。フィルタは与えられたパラメータに基づいてクエリの検索結果を絞り込みます。SQL 文においては、 [`QuerySet`](/ja/5.1/ref/models/querysets/#django.db.models.query.QuerySet) は `SELECT` 句、フィルタは `WHERE` や `LIMIT` のような絞り込みに用いる句に対応しています。

モデルの [`QuerySet`](/ja/5.1/ref/models/querysets/#django.db.models.query.QuerySet) を取得するには、モデルの [`Manager`](/ja/5.1/topics/db/managers/#django.db.models.Manager) を使用します。各モデルには少なくとも1つの [`Manager`](/ja/5.1/topics/db/managers/#django.db.models.Manager) があり、デフォルトでは [`objects`](/ja/5.1/ref/models/class/#django.db.models.Model.objects) という名前がついています。モデルクラスから直接アクセスしてください:

```pycon
>>> Blog.objects
<django.db.models.manager.Manager object at ...>
>>> b = Blog(name="Foo", tagline="Bar")
>>> b.objects
Traceback:
    ...
AttributeError: "Manager isn't accessible via Blog instances."
```

> **Note**
>
> `Manager` はモデルのインスタンスでなく、モデルのクラスを経由してのみアクセスでき、それは "テーブル水準" の処理と "レコード水準" の処理とで責任を明確に分離するためです。

[`Manager`](/ja/5.1/topics/db/managers/#django.db.models.Manager) はモデルの `QuerySet` の主な取得元になります。たとえば、 `Blog.objects.all()` はデータベース内の `Blog` オブジェクト全てを含んだ [`QuerySet`](/ja/5.1/ref/models/querysets/#django.db.models.query.QuerySet) を返します。

### すべてのオブジェクトを取得する

テーブルからオブジェクトを取得する最も簡単な方法は、全てのオブジェクトを取得することです。これを行うには、 [`Manager`](/ja/5.1/topics/db/managers/#django.db.models.Manager) の [`all()`](/ja/5.1/ref/models/querysets/#django.db.models.query.QuerySet.all) メソッドを使います:

```pycon
>>> all_entries = Entry.objects.all()
```

[`all()`](/ja/5.1/ref/models/querysets/#django.db.models.query.QuerySet.all) メソッドは、データベース内のすべてのオブジェクトを含んだ [`QuerySet`](/ja/5.1/ref/models/querysets/#django.db.models.query.QuerySet) を返します。

### フィルタを使って特定のオブジェクトを取得する

[`all()`](/ja/5.1/ref/models/querysets/#django.db.models.query.QuerySet.all) が返す [`QuerySet`](/ja/5.1/ref/models/querysets/#django.db.models.query.QuerySet) には、データベーステーブルのすべてのオブジェクトが含まれています。しかし、ふつう必要になるのはオブジェクト全体の集合ではなく、その部分集合でしょう。

そのような部分集合を作るには、条件フィルタを追加して最初の [`QuerySet`](/ja/5.1/ref/models/querysets/#django.db.models.query.QuerySet) を絞り込みます。 [`QuerySet`](/ja/5.1/ref/models/querysets/#django.db.models.query.QuerySet) を絞り込む代表的な方法として次の2つのものがあります。

**`filter(**kwargs)`**

  与えられたルックアップパラメータにマッチする新しい [`QuerySet`](/ja/5.1/ref/models/querysets/#django.db.models.query.QuerySet) を返します。

**`exclude(**kwargs)`**

  与えられたルックアップパラメータにマッチ *しない* 新しい [`QuerySet`](/ja/5.1/ref/models/querysets/#django.db.models.query.QuerySet) を返します。

ルックアップパラメータ (上の関数定義における `**kwargs` ) は、以下の [Field lookups](#field-lookups) で説明するフォーマットに従わなければなりません。

たとえば、2006年以降のブログエントリーの [`QuerySet`](/ja/5.1/ref/models/querysets/#django.db.models.query.QuerySet) を取得するには、 [`filter()`](/ja/5.1/ref/models/querysets/#django.db.models.query.QuerySet.filter) を次のように使用します。

```
Entry.objects.filter(pub_date__year=2006)
```

デフォルトの manager クラスの場合、これは次のコードと等価です。

```
Entry.objects.all().filter(pub_date__year=2006)
```

#### フィルタの連結

フィルタを行った [`QuerySet`](/ja/5.1/ref/models/querysets/#django.db.models.query.QuerySet) の結果自体も [`QuerySet`](/ja/5.1/ref/models/querysets/#django.db.models.query.QuerySet) です。そのため、複数のフィルタを連結することが可能です。たとえば、次のように書くことができます。

```pycon
>>> Entry.objects.filter(headline__startswith="What").exclude(
...     pub_date__gte=datetime.date.today()
... ).filter(pub_date__gte=datetime.date(2005, 1, 30))
```

これはデータベース内のすべてのエントリーを含む [`QuerySet`](/ja/5.1/ref/models/querysets/#django.db.models.query.QuerySet) をとり、フィルタを追加し、除外フィルタを追加し、さらにもう1つのフィルタを追加しています。最終的な結果は、"What" で始まるヘッドラインを持ち、2005年1月30日から今日までに公開されたすべてのエントリーを含んだ [`QuerySet`](/ja/5.1/ref/models/querysets/#django.db.models.query.QuerySet) となります。

#### フィルタを適用した `QuerySet` はユニーク

[`QuerySet`](/ja/5.1/ref/models/querysets/#django.db.models.query.QuerySet) に対してフィルタを適用するごとに、前の [`QuerySet`](/ja/5.1/ref/models/querysets/#django.db.models.query.QuerySet) から独立した完全に新しい [`QuerySet`](/ja/5.1/ref/models/querysets/#django.db.models.query.QuerySet) が作られます。フィルタごとに独立した [`QuerySet`](/ja/5.1/ref/models/querysets/#django.db.models.query.QuerySet) が作られるため、保存したり何度も再利用したりできます。

例:

```pycon
>>> q1 = Entry.objects.filter(headline__startswith="What")
>>> q2 = q1.exclude(pub_date__gte=datetime.date.today())
>>> q3 = q1.filter(pub_date__gte=datetime.date.today())
```

これら3つの `QuerySets` は独立しています。1番目は基本の [`QuerySet`](/ja/5.1/ref/models/querysets/#django.db.models.query.QuerySet) で、"What" で始まるヘッドラインを持つ全てのエントリーを含みます。2番めは1番目の部分集合で、 `pub_date` が今日または未来の日付であるレコードを除外する追加条件を持ちます。3番目も1番目の部分集合で、 `pub_date` が今日または未来の日付であるレコードだけを選択する追加条件を持ちます。1番目の [`QuerySet`](/ja/5.1/ref/models/querysets/#django.db.models.query.QuerySet) (`q1`) は、絞り込みの過程において何ら影響を受けません。

#### `QuerySet` は遅延評価される

`QuerySets` は遅延評価されます。 [`QuerySet`](/ja/5.1/ref/models/querysets/#django.db.models.query.QuerySet) を作る行為はいかなるデータベース操作も引き起こしません。たとえあなたが 1 日中フィルタのスタックを積み上げたとしても、[`QuerySet`](/ja/5.1/ref/models/querysets/#django.db.models.query.QuerySet) が *評価される* までは、Django は実際にはクエリを実行しません。次の例を見てください。

```pycon
>>> q = Entry.objects.filter(headline__startswith="What")
>>> q = q.filter(pub_date__lte=datetime.date.today())
>>> q = q.exclude(body_text__icontains="food")
>>> print(q)
```

この例ではデータベースに3回アクセスしているように見えますが、実際にアクセスしているのは、最終行 (`print(q)`) での1回だけです。一般に、 [`QuerySet`](/ja/5.1/ref/models/querysets/#django.db.models.query.QuerySet) の結果は、明示的に要求するまでデータベースから取得されません。取得するように要求した時点で、 [`QuerySet`](/ja/5.1/ref/models/querysets/#django.db.models.query.QuerySet) は *評価* され、データベースへのアクセスが発生します。評価が起こる正確なタイミングの詳細については、 [QuerySet が評価されるタイミング](/ja/5.1/ref/models/querysets/#when-querysets-are-evaluated) を参照してください。

### `get()` を使って1つのオブジェクトを取得する

[`filter()`](/ja/5.1/ref/models/querysets/#django.db.models.query.QuerySet.filter) は、たとえクエリーにマッチしたのが1つのオブジェクトだけだったとしても、常に [`QuerySet`](/ja/5.1/ref/models/querysets/#django.db.models.query.QuerySet) を返します。この場合、 [`QuerySet`](/ja/5.1/ref/models/querysets/#django.db.models.query.QuerySet) には1つの要素だけが含まれることになります。

クエリーにマッチするのは1つのオブジェクトだけだと分かっている場合、  [`Manager`](/ja/5.1/topics/db/managers/#django.db.models.Manager) の [`get()`](/ja/5.1/ref/models/querysets/#django.db.models.query.QuerySet.get) メソッドを呼べば、そのオブジェクトが直接返されます。

```pycon
>>> one_entry = Entry.objects.get(pk=1)
```

[`filter()`](/ja/5.1/ref/models/querysets/#django.db.models.query.QuerySet.filter) と同じように、 [`get()`](/ja/5.1/ref/models/querysets/#django.db.models.query.QuerySet.get) には任意のクエリー表現が使用できます。 繰り返しますが、詳しくはあとで説明する [Field lookups](#field-lookups) を見てください。

[`get()`](/ja/5.1/ref/models/querysets/#django.db.models.query.QuerySet.get) と [`filter()`](/ja/5.1/ref/models/querysets/#django.db.models.query.QuerySet.filter) を `[0]` でスライスすることには、次のような違いがあることに注意してください。クエリにマッチする結果が存在しない場合、 [`get()`](/ja/5.1/ref/models/querysets/#django.db.models.query.QuerySet.get) は `DoesNotExist` 例外を起こします。この例外はクエリーが実行されるモデルクラスの属性です。たとえば上のコードでは、1というプライマリーキーを持つ `Entry` オブジェクトがなければ、Django は `Entry.DoesNotExist` 例外を起こします。

同様に [`get()`](/ja/5.1/ref/models/querysets/#django.db.models.query.QuerySet.get) のクエリーが2つ以上のアイテムにマッチした場合にも、Djangoは文句を言います。この場合には、やはり同じクエリのモデルクラスの属性の [`MultipleObjectsReturned`](/ja/5.1/ref/exceptions/#django.core.exceptions.MultipleObjectsReturned) 例外が起こります。

### その他の `QuerySet` メソッド

データベースからオブジェクトを検索する必要がある大抵の場合は、 [`all()`](/ja/5.1/ref/models/querysets/#django.db.models.query.QuerySet.all), [`get()`](/ja/5.1/ref/models/querysets/#django.db.models.query.QuerySet.get), [`filter()`](/ja/5.1/ref/models/querysets/#django.db.models.query.QuerySet.filter) および [`exclude()`](/ja/5.1/ref/models/querysets/#django.db.models.query.QuerySet.exclude) のいずれかを使うことになるでしょう。しかしこれらのメソッドだけでは不十分な場合は、さまざまな [`QuerySet`](/ja/5.1/ref/models/querysets/#django.db.models.query.QuerySet) メソッドの全リストが掲載されている [QuerySet API リファレンス](/ja/5.1/ref/models/querysets/#queryset-api) を参照してください。

### `QuerySet` の要素数を制限する

Python のリストスライスのサブセットを使うことで [`QuerySet`](/ja/5.1/ref/models/querysets/#django.db.models.query.QuerySet) の結果を特定の要素数に制限できます。これは SQL の `LIMIT` と `OFFSET` 句に対応します。

たとえば、次のコードは最初の5つのオブジェクトを返します (`LIMIT 5`)。

```pycon
>>> Entry.objects.all()[:5]
```

次のコードは、6番目から10番目までのオブジェクトを返します (`OFFSET 5 LIMIT 5`)。

```pycon
>>> Entry.objects.all()[5:10]
```

負のインデックスには対応していません (例: `Entry.objects.all()[-1]`)。

一般に、 [`QuerySet`](/ja/5.1/ref/models/querysets/#django.db.models.query.QuerySet) をスライスしたとしても、新しい [`QuerySet`](/ja/5.1/ref/models/querysets/#django.db.models.query.QuerySet) が返り、クエリーの評価は行われません。例外は、Python のリストスライス構文の "step" パラメーターを使用した場合です。たとえば、次のコードは実際にクエリを実行し、最初の10個のオブジェクトから一つおきにとったオブジェクトのリストを返します。

```pycon
>>> Entry.objects.all()[:10:2]
```

スライスされたクエリーセットのフィルタリングやソートは、動作が曖昧なため禁止されています。

リスト (例: `SELECT foo FROM bar LIMIT 1`) ではなく *1つの* オブジェクトを取得するには、スライスではなくリストのインデックスを使用してください。たとえば、次のコードは、ヘッドラインでアルファベット順にソートしたあと、データベースの1番目の `Entry` を返します。

```pycon
>>> Entry.objects.order_by("headline")[0]
```

上の例は次のコードとほとんど同じです。

```pycon
>>> Entry.objects.order_by("headline")[0:1].get()
```

ただし、与えられた条件を満たすオブジェクトが存在しない場合に、前者は `IndexError` を起こすのに対して、後者は `DoesNotExist` を起こすことに注意してください。詳細については [`get()`](/ja/5.1/ref/models/querysets/#django.db.models.query.QuerySet.get) を参照してください。

### フィールドルックアップ

フィールドルックアップは、SQL の `WHERE` 句の内容を指定する手段です。 [`QuerySet`](/ja/5.1/ref/models/querysets/#django.db.models.query.QuerySet) メソッド、 [`filter()`](/ja/5.1/ref/models/querysets/#django.db.models.query.QuerySet.filter) 、 [`exclude()`](/ja/5.1/ref/models/querysets/#django.db.models.query.QuerySet.exclude) および [`get()`](/ja/5.1/ref/models/querysets/#django.db.models.query.QuerySet.get) にキーワード引数として指定します。

基本のルックアップキーワード引数は `field__lookuptype=value` という形を取ります (2文字連続するアンダースコアです)。たとえば、

```pycon
>>> Entry.objects.filter(pub_date__lte="2006-01-01")
```

というコードは、(だいたい) 次の SQL 文に変換されます。

```sql
SELECT * FROM blog_entry WHERE pub_date <= '2006-01-01';
```

> **動作のしくみ**
>
> Python には任意の name-value 形式の引数をとる関数を定義する能力があり、name と value の値を実行時に評価します。詳しい情報については、公式の Python チュートリアルの [Keyword Arguments](https://docs.python.org/3/tutorial/controlflow.html#tut-keywordargs) を参照してください。

ルックアップに指定するフィールドはモデルが持つフィールド名でなければなりません。ただし1つだけ例外があり、 [`ForeignKey`](/ja/5.1/ref/models/fields/#django.db.models.ForeignKey) の場合にはフィールド名の末尾に `_id` を付けた名前を指定できます。その場合、value  パラメータには外部モデルのプライマリーキーの生の値を書くことが期待されます。

```pycon
>>> Entry.objects.filter(blog_id=4)
```

無効なキーワード引数を指定すると、ルックアップ関数は `TypeError` を起こします。

データベース API は約30個のルックアップタイプをサポートしており、完全なガイドは [フィールドルックアップのリファレンス](/ja/5.1/ref/models/querysets/#field-lookups) で見ることができます。ルックアップを使って何ができるのかがよく分かるように、以下によく使う一般的なルックアップをいくつか挙げます。

**[`exact`](/ja/5.1/ref/models/querysets/#std-fieldlookup-exact)**

  完全な ("exact") マッチを行います。たとえば、

  ```pycon
  >>> Entry.objects.get(headline__exact="Cat bites dog")
  ```

  は次のような SQL を生成します。

  ```sql
  SELECT ... WHERE headline = 'Cat bites dog';
  ```

  ルックアップタイプを指定しなかった場合、つまりキーワード引数がダブルアンダースコアを含まない場合、ルックアップタイプは `exact` が指定されたものとみなされます。

  たとえば、次の2つの文は等価です。

  ```pycon
  >>> Blog.objects.get(id__exact=14)  # Explicit form
  >>> Blog.objects.get(id=14)  # __exact is implied
  ```

  `exact` ルックアップが最もよく使われるため、利便性のためにこのようになっています。

**[`iexact`](/ja/5.1/ref/models/querysets/#std-fieldlookup-iexact)**

  case-insensitive  なマッチを行います。したがって、次のクエリ

  ```pycon
  >>> Blog.objects.get(name__iexact="beatles blog")
  ```

  は `"Beatles Blog"`、 `"beatles blog"`、あるいは `"BeAtlES blOG"` というタイトルを持つ `Blog` にもマッチします。

**[`contains`](/ja/5.1/ref/models/querysets/#std-fieldlookup-contains)**

  case-sensitive な部分一致テストを行います。たとえば、

  ```
  Entry.objects.get(headline__contains="Lennon")
  ```

  はだいたい次のような SQL に変換されます。

  ```sql
  SELECT ... WHERE headline LIKE '%Lennon%';
  ```

  この例では、ヘッドライン `'Today Lennon honored'` にはマッチしても `'today lennon honored'` にはマッチしないことに注意してください。

  case-insensitive バージョンの [`icontains`](/ja/5.1/ref/models/querysets/#std-fieldlookup-icontains) もあります。

**[`startswith`](/ja/5.1/ref/models/querysets/#std-fieldlookup-startswith) と [`endswith`](/ja/5.1/ref/models/querysets/#std-fieldlookup-endswith)**

  それぞれ starts-with と ends-with 検索を行います。case-insensitive バージョン [`istartswith`](/ja/5.1/ref/models/querysets/#std-fieldlookup-istartswith) と [`iendswith`](/ja/5.1/ref/models/querysets/#std-fieldlookup-iendswith) もあります。

繰り返しになりますが、以上はルックアップの表面をさらったに過ぎません。完全なリファレンスは [フィールドルックアップのリファレンス](/ja/5.1/ref/models/querysets/#field-lookups) を参照してください。

### リレーションシップを横断するルックアップ

Django はルックアップの中でリレーションシップを「横断する」強力で直感的な方法を提供します。あなたのために、背後で SQL の `JOIN` を自動的に実行しています。リレーションシップを横断するには、使いたいフィールドにたどり着くまで、モデル間を横断する関連フィールドのフィールド名をダブルアンダースコアで繋ぎます。

次の例は、`name` に `'Beatles Blog'` を持つ `Blog` のすべての `Entry` オブジェクトを取得します。

```pycon
>>> Entry.objects.filter(blog__name="Beatles Blog")
```

この横断は好きなだけ深くすることができます。

逆方向にも動作します。 [`カスタマイズすることもできます`](/ja/5.1/ref/models/fields/#django.db.models.ForeignKey.related_query_name) が、デフォルトでは、モデルの小文字の名前を使用して、ルックアップで「逆」リレーションシップを参照します。

次の例は、少なくとも1つの `headline` が `'Lennon'` を含む `Entry` を持つ、すべての `Blog` オブジェクトを取得します。

```pycon
>>> Blog.objects.filter(entry__headline__contains="Lennon")
```

複数のリレーションにまたがってフィルタリングをしていて、中間モデルのどれかが条件に合致しない場合、Django は空 (すべての値が `NULL`) だが有効なオブジェクトとして扱います。これは、エラーにはならないということです。たとえば以下のフィルタでは、

```
Blog.objects.filter(entry__authors__name="Lennon")
```

（リレーションシップを持つ `Author` モデルがあったとして、）もしあるエントリに関連付けられた `author` がいなかった場合、`author` が無いことを理由にエラーになるのではなく、単に `name` が無かったかのように扱われます。通常はこれが望ましい動作です。もし混乱するとしたら、[`isnull`](/ja/5.1/ref/models/querysets/#std-fieldlookup-isnull) を使う場合でしょう。つまり、

```
Blog.objects.filter(entry__authors__name__isnull=True)
```

これは、`author` の `name` が空であるような `Blog` オブジェクトと、`entry` の `author` が空であるような `Blog` オブジェクトの両方を返します。後者のオブジェクトが欲しくない場合は、次のように書きます。

```
Blog.objects.filter(entry__authors__isnull=False, entry__authors__name__isnull=True)
```

#### 複数の値を持つリレーションシップの横断

[`ManyToManyField`](/ja/5.1/ref/models/fields/#django.db.models.ManyToManyField) や逆の [`ForeignKey`](/ja/5.1/ref/models/fields/#django.db.models.ForeignKey) (例えば `Blog` から `Entry` へ) をまたぐとき、複数の属性でフィルタリングを行う場合、それぞれの属性がリレーション先の同一オブジェクト内で同時に一致する必要があるのかどうかが問題になります。「2008年に公開された、見出しに *“Lennon”* が含まれるエントリ」を持つブログを探したいかもしれませんし、「2008年に公開されたエントリを持ち、かつ2008年より新しいか古い、見出しに *“Lennon”* の含まれた別のエントリを持つブログ」を探したいかも知れません。

少なくとも1つの2008年のエントリーを含み、かつそのエントリーに「Lennon」というヘッドラインが含まれている（同じエントリーが両方の条件を満たしている）ブログをすべて取得する場合、このように書きます:

```
Blog.objects.filter(entry__headline__contains="Lennon", entry__pub_date__year=2008)
```

一方、ヘッドラインに「Lennon」が含まれる *何らか* のエントリーと、2008年の *何らかの* エントリーを持つ任意のブログを取得する寛容なクエリを実行する場合は、次のように書きます:

```
Blog.objects.filter(entry__headline__contains="Lennon").filter(
    entry__pub_date__year=2008
)
```

*"Lennon "* を含むエントリーと2008年のエントリーの両方を持つブログが1つだけあり、2008年のエントリーには *"Lennon "* が含まれていなかったとします。最初のクエリはどのブログも返しませんが、2番目のクエリはその1つのブログを返します (これは、2番目のフィルタによって選択されたエントリーが1番目のフィルタのエントリーと違っていても構わないからです。私たちはそれぞれのフィルタ文で、 `Entry` アイテムではなく、 `Blog` アイテムをフィルタしているのです)。つまり、各条件がリレーション先の同じオブジェクトにマッチする必要がある場合、それぞれを 1 つの [`filter()`](/ja/5.1/ref/models/querysets/#django.db.models.query.QuerySet.filter) 呼び出しに含める必要があります。

> **Note**
>
> 2番目の (より寛容な) クエリは複数のフィルタを連鎖させるので、最初のモデルに複数の結合を実行し、重複を生成することがあります。
>
> ```pycon
> >>> from datetime import date
> >>> beatles = Blog.objects.create(name="Beatles Blog")
> >>> pop = Blog.objects.create(name="Pop Music Blog")
> >>> Entry.objects.create(
> ...     blog=beatles,
> ...     headline="New Lennon Biography",
> ...     pub_date=date(2008, 6, 1),
> ... )
> <Entry: New Lennon Biography>
> >>> Entry.objects.create(
> ...     blog=beatles,
> ...     headline="New Lennon Biography in Paperback",
> ...     pub_date=date(2009, 6, 1),
> ... )
> <Entry: New Lennon Biography in Paperback>
> >>> Entry.objects.create(
> ...     blog=pop,
> ...     headline="Best Albums of 2008",
> ...     pub_date=date(2008, 12, 15),
> ... )
> <Entry: Best Albums of 2008>
> >>> Entry.objects.create(
> ...     blog=pop,
> ...     headline="Lennon Would Have Loved Hip Hop",
> ...     pub_date=date(2020, 4, 1),
> ... )
> <Entry: Lennon Would Have Loved Hip Hop>
> >>> Blog.objects.filter(
> ...     entry__headline__contains="Lennon",
> ...     entry__pub_date__year=2008,
> ... )
> <QuerySet [<Blog: Beatles Blog>]>
> >>> Blog.objects.filter(
> ...     entry__headline__contains="Lennon",
> ... ).filter(
> ...     entry__pub_date__year=2008,
> ... )
> <QuerySet [<Blog: Beatles Blog>, <Blog: Beatles Blog>, <Blog: Pop Music Blog]>
> ```

> **Note**
>
> 上記のような複数の値のリレーションシップをまたぐクエリに対する [`filter()`](/ja/5.1/ref/models/querysets/#django.db.models.query.QuerySet.filter) の動作は、 [`exclude()`](/ja/5.1/ref/models/querysets/#django.db.models.query.QuerySet.exclude) と同等には実装されていません。その代わり、1つの [`exclude()`](/ja/5.1/ref/models/querysets/#django.db.models.query.QuerySet.exclude) 呼び出しにおける条件は必ずしも同じアイテムを参照するとは限りません。
>
> 例えば、以下のクエリは、見出しに *"Lennon"* を含むエントリー *と* 、2008年に公開されたエントリーの *両方* を含むブログを除外します:
>
> ```
> Blog.objects.exclude(
>     entry__headline__contains="Lennon",
>     entry__pub_date__year=2008,
> )
> ```
>
> しかし、 [`filter()`](/ja/5.1/ref/models/querysets/#django.db.models.query.QuerySet.filter) を使ったときの動作とは異なり、このクエリは両方の条件を満たすエントリでブログを絞り込むわけではありません。つまり、「2008年に *"Lennon"* によって公開されたエントリー」を含まないブログすべてを取得するには、このように2つのクエリを書く必要があります:
>
> ```
> Blog.objects.exclude(
>     entry__in=Entry.objects.filter(
>         headline__contains="Lennon",
>         pub_date__year=2008,
>     ),
> )
> ```

### フィルタはモデルのフィールドを参照できる

今まで見てきた例では、モデルのフィールドの値を定数と比較するフィルタを作ってきました。しかし、もしモデルのフィールドの値を、同じモデルの他のフィールドと比較したい時にはどうすればいいのでしょう？

そのような比較を行うために、Django は [`F 式`](/ja/5.1/ref/models/expressions/#django.db.models.F) を用意しています。 `F()` のインスタンスは、クエリの中でモデルのフィールドへの参照として振る舞います。したがって、この参照をクエリの中で使うことで、同じモデルのインスタンスの異なる2つのフィールドの値を比較できます。

たとえば、pingback の数よりコメントの数のほうが多いすべてのブログエントリーのリストを検索するには、pingback の数を参照する `F()` オブジェクトを作り、その `F()` オブジェクトをクエリの中で次のように使います。

```pycon
>>> from django.db.models import F
>>> Entry.objects.filter(number_of_comments__gt=F("number_of_pingbacks"))
```

Django は `F()` オブジェクトを使った足し算、引き算、掛け算、割り算、モジュロ、累乗算術を、定数や他の `F()` オブジェクトとの両方でサポートしています。コメント数がピンバック数の *2倍* を超えるブログエントリをすべて見つけるには、このようにクエリを変更します:

```pycon
>>> Entry.objects.filter(number_of_comments__gt=F("number_of_pingbacks") * 2)
```

エントリーのレーティングがピンバック数とコメント数の合計より少ないエントリーをすべて見つけるには、次のようなクエリを発行します:

```pycon
>>> Entry.objects.filter(rating__lt=F("number_of_comments") + F("number_of_pingbacks"))
```

`F()` オブジェクトのリレーションシップに 2重アンダースコア表記を使うこともできます。 `F()` オブジェクトに2重アンダースコアを付けると、リレーション先オブジェクトにアクセスするために必要な結合を行うことができます。例えば、作者名がブログ名と同じすべてのエントリを取得するには、次のようなクエリを発行します:

```pycon
>>> Entry.objects.filter(authors__name=F("blog__name"))
```

日付と日付/時刻フィールドには、 [`timedelta`](https://docs.python.org/3/library/datetime.html#datetime.timedelta) オブジェクトを足し引きできます。次のようにすると、公開から3日以上経ってから更新されたすべてのエントリーが返されます:

```pycon
>>> from datetime import timedelta
>>> Entry.objects.filter(mod_date__gt=F("pub_date") + timedelta(days=3))
```

`F()` オブジェクトは `.bitand()`, `.bitor()`, `.bitxor()`, `.bitrightshift()`, `.bitleftshift()` によるビット演算をサポートしています。例えばこのようにします:

```pycon
>>> F("somefield").bitand(16)
```

> **Oracle**
>
> オラクルはXORビット演算をサポートしていません。

### 式はトランスフォーム（Transform）を参照できる

Django は式でトランスフォーム（変換）を使うことをサポートしています。

たとえば、次のコードは最終更新年と同じ年に発行されたすべてのEntryオブジェクトを検索します:

```pycon
>>> from django.db.models import F
>>> Entry.objects.filter(pub_date__year=F("mod_date__year"))
```

最も古い出版年を調べるには、次のクエリを実行します:

```pycon
>>> from django.db.models import Min
>>> Entry.objects.aggregate(first_published_year=Min("pub_date__year"))
```

たとえばこの例では、各年の最高評価エントリーの値と、全エントリーに対するコメントの総数を求めています:

```pycon
>>> from django.db.models import OuterRef, Subquery, Sum
>>> Entry.objects.values("pub_date__year").annotate(
...     top_rating=Subquery(
...         Entry.objects.filter(
...             pub_date__year=OuterRef("pub_date__year"),
...         )
...         .order_by("-rating")
...         .values("rating")[:1]
...     ),
...     total_comments=Sum("number_of_comments"),
... )
```

### `pk` ルックアップショートカット

利便性のために、Django は `pk` ルックアップショートカットを用意しています。pk とは "primary key" を表します。

例の `Blog` モデルでは、プライマリキーは `id` フィールドなので、次の3つの文は等価です:

```pycon
>>> Blog.objects.get(id__exact=14)  # Explicit form
>>> Blog.objects.get(id=14)  # __exact is implied
>>> Blog.objects.get(pk=14)  # pk implies id__exact
```

`pk` は、 `__exact` クエリ以外でも使えます。好きなクエリ語句を `pk` と組み合わせて、モデルのプライマリキーに対するクエリを実行できます:

```pycon
# Get blogs entries with id 1, 4 and 7
>>> Blog.objects.filter(pk__in=[1, 4, 7])

# Get all blog entries with id > 14
>>> Blog.objects.filter(pk__gt=14)
```

`pk` ルックアップは結合をまたいでも動作します。たとえば、次の3つの文は等価です:

```pycon
>>> Entry.objects.filter(blog__id__exact=3)  # Explicit form
>>> Entry.objects.filter(blog__id=3)  # __exact is implied
>>> Entry.objects.filter(blog__pk=3)  # __pk implies __id__exact
```

### `LIKE` 文の中ではパーセント記号とアンダースコアがエスケープされる

`LIKE` SQL文 (`iexact`, `contains`, `icontains`, `startswith`, `istartswith`, `endswith`, `iendswith`) に相当するフィールドルックアップでは、 `LIKE` 文で使用される2つの特殊文字 (パーセント記号とアンダースコア) が自動的にエスケープされます。 (`LIKE` 文では、パーセント記号は複数文字のワイルドカードを意味し、アンダースコアは1文字のワイルドカードを意味します)。

つまり、直感的に動作するので、抽象化が漏れることはありません。たとえば、パーセント記号を含むすべてのエントリを取得するには、パーセント記号を他の文字と同じように使用します:

```pycon
>>> Entry.objects.filter(headline__contains="%")
```

Django は以下のように、あなたの代わりにクォート処理をしてくれます:

```sql
SELECT ... WHERE headline LIKE '%\%%';
```

アンダースコアも同様です。パーセント記号もアンダースコアも透過的に処理されます。

### キャッシュと `QuerySet`

それぞれの [`QuerySet`](/ja/5.1/ref/models/querysets/#django.db.models.query.QuerySet) には、データベースへのアクセスを最小にするために内部にキャッシュがあります。キャッシュのしくみを理解すれば、最も効率の良いコードが書けるようになります。

新しく作成された [`QuerySet`](/ja/5.1/ref/models/querysets/#django.db.models.query.QuerySet) では、キャッシュは空です。初めて [`QuerySet`](/ja/5.1/ref/models/querysets/#django.db.models.query.QuerySet) が評価されたとき、つまりデータベースへのクエリが発生したとき、Django はクエリの結果を [`QuerySet`](/ja/5.1/ref/models/querysets/#django.db.models.query.QuerySet) のキャッシュに保存し、明示的に要求された結果 (例えば、 [`QuerySet`](/ja/5.1/ref/models/querysets/#django.db.models.query.QuerySet) が繰り返し処理されている場合は次の要素) を返します。それ以降の [`QuerySet`](/ja/5.1/ref/models/querysets/#django.db.models.query.QuerySet) の評価はキャッシュされた結果を再利用します。

このキャッシュの動作は覚えておきましょう。 [`QuerySet`](/ja/5.1/ref/models/querysets/#django.db.models.query.QuerySet) を正しく使わないと、痛い目を見るかもしれません。たとえば、次のようにしてしまうと [`QuerySet`](/ja/5.1/ref/models/querysets/#django.db.models.query.QuerySet) が 2 つ作成され、評価され、そして破棄されます:

```pycon
>>> print([e.headline for e in Entry.objects.all()])
>>> print([e.pub_date for e in Entry.objects.all()])
```

つまり、同じデータベースクエリが2回実行されることになり、事実上データベースの負荷が2倍になります。また、2つのリクエストの間の一瞬の間に `Entry` が追加されたり削除されたりして、2つのリストに同じデータベースレコードが含まれない可能性もあります。

この問題を回避するには、 [`QuerySet`](/ja/5.1/ref/models/querysets/#django.db.models.query.QuerySet) を保存して再利用します:

```pycon
>>> queryset = Entry.objects.all()
>>> print([p.headline for p in queryset])  # Evaluate the query set.
>>> print([p.pub_date for p in queryset])  # Reuse the cache from the evaluation.
```

#### `QuerySet` がキャッシュされないケース

クエリセットは常に結果をキャッシュするわけではありません。 クエリセットの *一部* だけを評価する場合、キャッシュがチェックされますが、もしキャッシュに値が入力されていなければ、後続のクエリで返される項目はキャッシュされません。具体的には、配列のスライスやインデックスを使用して [クエリセットを制限](#limiting-querysets) しても、キャッシュは生成されません。

たとえば、クエリセットオブジェクトで特定のインデックスを繰り返し取得すると、その度にデータベースにクエリが送られます:

```pycon
>>> queryset = Entry.objects.all()
>>> print(queryset[5])  # Queries the database
>>> print(queryset[5])  # Queries the database again
```

しかし、クエリセット全体がすでに評価されている場合は、代わりにキャッシュが調べられます:

```pycon
>>> queryset = Entry.objects.all()
>>> [entry for entry in queryset]  # Queries the database
>>> print(queryset[5])  # Uses cache
>>> print(queryset[5])  # Uses cache
```

以下に、クエリセット全体が評価され、その結果キャッシュに入力される他の操作の例をいくつか示します:

```pycon
>>> [entry for entry in queryset]
>>> bool(queryset)
>>> entry in queryset
>>> list(queryset)
```

> **Note**
>
> 単にクエリセットを表示するだけではキャッシュにデータを入れることはできません。これは `__repr__()` の呼び出しがクエリセット全体のスライスを返すだけだからです。

## 非同期クエリ

非同期ビューやコードを書いている場合、上記で説明した方法でORMをクエリに使用することはできません。非同期コードから *ブロッキングな* 同期コードを呼び出すことはできず、イベントループをブロックしてしまいます（それか、大抵はDjangoがそのことを検出し、 `SynchronousOnlyOperation` を発生させて防ぐでしょう）。

幸い、Django の非同期クエリ API を使えば、多くのクエリを実行できます。 `get()` や  `delete()` のようなブロッキングされる可能性のあるメソッドにはすべて非同期型 (`aget()` や `adelete()`) があり、結果を反復処理するときには、代わりに非同期反復処理 (`async for`) が使えます。

### クエリの繰り返し（イテレーション）

クエリを繰り返し処理するデフォルトの方法 `for` では、 Django が繰り返し処理時に結果をロードするため、裏でデータベースのクエリがブロッキングされます。これを修正するには、 `async for` に変更します:

```
async for entry in Authors.objects.filter(name__startswith="A"):
    ...
```

例えば、 `list()` をクエリセットにラップして強制的にクエリセットを評価するようなことはできません (必要であれば、内包表記の中で `async for` を使うことができます)。

`filter()` や `exclude()` のような `QuerySet` メソッドは実際にクエリを実行するわけではなく、クエリセットがイテレートされたときに実行されるように指定するものなので、非同期コードで自由に使用できます。どのメソッドがこのように使い続けられるか、またどのメソッドに非同期バージョンがあるかについては、次のセクションを読んでください。

### `QuerySet` とマネージャメソッド

マネージャやクエリセットに関するメソッドの中には、 `get()` や `first()` のように、クエリセットを強制的に実行し、ブロッキングするものがあります。 `filter()` や `exclude()` のように、実行を強制しないメソッドもあります。しかし、どうやって見分けるのでしょうか？

メソッドに `a` で始まるバージョンがあるかどうかを探ることもできます（例えば、`aget()` はありますが、 `afilter()` はありません）。しかし、もっとロジカルな方法があります。それは、 [QuerySet リファレンス](/ja/5.1/ref/models/querysets/) でそのメソッドがどのような種類のものかを調べることです。

そこでは、QuerySet に関するメソッドを2つのセクションに分けています:

- *新しいクエリセットを返すメソッド*: これらはノンブロッキングのもので、非同期バージョンはありません。これらはどんな状況でも自由に使うことができますが、使う前に `defer()` と `only()` に関する注意事項を読んでください。
- *クエリセットを返さないメソッド*: これらはブロッキングメソッドで、非同期バージョンもあります。それぞれの非同期名はドキュメントに書かれていますが、私たちの標準的なパターンは接頭辞に `a` をつけることです。

この区別を使えば、非同期バージョンを使う必要があるときとないときを判断できます。たとえば、これは有効な非同期クエリです:

```
user = await User.objects.filter(username=my_input).afirst()
```

`filter()` はクエリセットを返すため、非同期環境内で連結して使用しても問題ありません。一方で `first()` は評価してモデルインスタンスを返すため、 `afirst()` に変更し、非同期に適した方法で呼び出すために、式全体の前に `await` を使用します。

> **Note**
>
> もし `await` の部分を入れ忘れると、 *"coroutine object has no attribute x "* や *"\<coroutine ...\>"* のようなエラーがモデルインスタンスの代わりに表示されるかもしれません。このようなエラーが表示される場合は、コルーチンを実際の値に変換するための `await` 部分が不足しています。

### トランザクション

トランザクションは現在、非同期クエリや更新ではサポートされていません。これを使用しようとすると `SynchronousOnlyOperation` が発生します。

トランザクションを使用したい場合は、ORMコードを別の同期関数の中に記述し、 `sync_to_async` を使用して呼び出すことをおすすめします。詳しくは [非同期サポート](/ja/5.1/topics/async/) を参照してください。

## `JSONField` へのクエリ

[`JSONField`](/ja/5.1/ref/models/fields/#django.db.models.JSONField) では、ルックアップの実装は主にキーのトランスフォーム（変換）の存在によって異なります。デモンストレーションのために、次のモデル例を使います:

```
from django.db import models

class Dog(models.Model):
    name = models.CharField(max_length=200)
    data = models.JSONField(null=True)

    def __str__(self):
        return self.name
```

### `None` の保存とクエリ

他のフィールドと同様に、フィールドの値として `None` を格納すると、SQL の `NULL` として格納されます。推奨はしませんが、 [`Value(None, JSONField())`](/ja/5.1/ref/models/expressions/#django.db.models.Value) を使用することで、 SQL の `NULL` の代わりに JSON のスカラー値 `null` を格納できます。

どちらの値が格納されていても、データベースから取得したとき、JSON のスカラー `null` の Python 表現は SQL の `NULL` と同じ、つまり `None` になります。そのため、両者を区別するのは難しいでしょう。

これはフィールドのトップレベルの値としての `None` にだけ適用されます。もし `None` が [`list`](https://docs.python.org/3/library/stdtypes.html#list) や [`dict`](https://docs.python.org/3/library/stdtypes.html#dict) の中にある場合、常に JSON の `null` として解釈されます。

クエリの際、 `None` 値は常に JSON `null` として解釈されます。SQL の `NULL` をクエリするには [`isnull`](/ja/5.1/ref/models/querysets/#std-fieldlookup-isnull) を使用します:

```pycon
>>> Dog.objects.create(name="Max", data=None)  # SQL NULL.
<Dog: Max>
>>> Dog.objects.create(name="Archie", data=Value(None, JSONField()))  # JSON null.
<Dog: Archie>
>>> Dog.objects.filter(data=None)
<QuerySet [<Dog: Archie>]>
>>> Dog.objects.filter(data=Value(None, JSONField()))
<QuerySet [<Dog: Archie>]>
>>> Dog.objects.filter(data__isnull=True)
<QuerySet [<Dog: Max>]>
>>> Dog.objects.filter(data__isnull=False)
<QuerySet [<Dog: Archie>]>
```

SQL の `NULL` 値を使いたいのでなければ、 `null=False` を設定し、 `default=dict` のように空の値に対して適切なデフォルト値を指定することを検討してください。

> **Note**
>
> JSON スカラー値の `null` を格納することは [`null=False`](/ja/5.1/ref/models/fields/#django.db.models.Field.null) に反しません。

### キー、インデックス、パス（経路）のトランスフォーム（変換）

指定された辞書のキーに基づいてクエリを実行するには、そのキーをルックアップ名として使います:

```pycon
>>> Dog.objects.create(
...     name="Rufus",
...     data={
...         "breed": "labrador",
...         "owner": {
...             "name": "Bob",
...             "other_pets": [
...                 {
...                     "name": "Fishy",
...                 }
...             ],
...         },
...     },
... )
<Dog: Rufus>
>>> Dog.objects.create(name="Meg", data={"breed": "collie", "owner": None})
<Dog: Meg>
>>> Dog.objects.filter(data__breed="collie")
<QuerySet [<Dog: Meg>]>
```

複数のキーを連結して1本のルックアップパス（経路）を形成することもできます。

```pycon
>>> Dog.objects.filter(data__owner__name="Bob")
<QuerySet [<Dog: Rufus>]>
```

キーが整数の場合は、配列のインデックスのトランスフォームとして解釈されます:

```pycon
>>> Dog.objects.filter(data__owner__other_pets__0__name="Fishy")
<QuerySet [<Dog: Rufus>]>
```

クエリしたいキーが他のルックアップ名と衝突する場合は、代わりに [`contains`](#std-fieldlookup-jsonfield.contains) ルックアップを使用してください。

欠損したキーをクエリで探したいときは、 `isnull` ルックアップを使用します:

```pycon
>>> Dog.objects.create(name="Shep", data={"breed": "collie"})
<Dog: Shep>
>>> Dog.objects.filter(data__owner__isnull=True)
<QuerySet [<Dog: Shep>]>
```

> **Note**
>
> 上記のルックアップ例は暗黙的に [`exact`](/ja/5.1/ref/models/querysets/#std-fieldlookup-exact) ルックアップを使用しています。キー、インデックス、およびパス（経路）のトランスフォーム（変換）は、 [`icontains`](/ja/5.1/ref/models/querysets/#std-fieldlookup-icontains), [`endswith`](/ja/5.1/ref/models/querysets/#std-fieldlookup-endswith), [`iendswith`](/ja/5.1/ref/models/querysets/#std-fieldlookup-iendswith), [`iexact`](/ja/5.1/ref/models/querysets/#std-fieldlookup-iexact), [`regex`](/ja/5.1/ref/models/querysets/#std-fieldlookup-regex), [`iregex`](/ja/5.1/ref/models/querysets/#std-fieldlookup-iregex), [`startswith`](/ja/5.1/ref/models/querysets/#std-fieldlookup-startswith), [`istartswith`](/ja/5.1/ref/models/querysets/#std-fieldlookup-istartswith), [`lt`](/ja/5.1/ref/models/querysets/#std-fieldlookup-lt), [`lte`](/ja/5.1/ref/models/querysets/#std-fieldlookup-lte), [`gt`](/ja/5.1/ref/models/querysets/#std-fieldlookup-gt), および [`gte`](/ja/5.1/ref/models/querysets/#std-fieldlookup-gte) に加え、 [contain の概念とキーのルックアップ](#containment-and-key-lookups) とも連結できます。

#### `KT()` 式

#### `class KT(lookup)`

[`JSONField`](/ja/5.1/ref/models/fields/#django.db.models.JSONField) のキー、インデックス、パス（経路）のトランスフォーム（変換）のテキスト値を表します。 `lookup` で2重アンダースコア表記を使用すると、辞書のキーやインデックス変換を連結できます。

例えば次のようにします:

```pycon
>>> from django.db.models.fields.json import KT
>>> Dog.objects.create(
...     name="Shep",
...     data={
...         "owner": {"name": "Bob"},
...         "breed": ["collie", "lhasa apso"],
...     },
... )
<Dog: Shep>
>>> Dog.objects.annotate(
...     first_breed=KT("data__breed__1"), owner_name=KT("data__owner__name")
... ).filter(first_breed__startswith="lhasa", owner_name="Bob")
<QuerySet [<Dog: Shep>]>
```

> **Note**
>
> キーパスクエリの動作上、 [`exclude()`](/ja/5.1/ref/models/querysets/#django.db.models.query.QuerySet.exclude) と [`filter()`](/ja/5.1/ref/models/querysets/#django.db.models.query.QuerySet.filter) は網羅的なセットを生成することを保証しません。パスを持たないオブジェクトを含めたい場合は、 `isnull` ルックアップを追加してください。

> **Warning**
>
> JSON オブジェクトでは、どのような文字列もキーになる可能性があるため、以下に示す以外のルックアップはキーのルックアップとして解釈されます。エラーは発生しません。タイプミスに十分注意し、クエリが意図したとおりに動作することを常に確認してください。

> **MariaDB または Oracle ユーザーの場合**
>
> キー、インデックス、パスのトランスフォームで [`order_by()`](/ja/5.1/ref/models/querysets/#django.db.models.query.QuerySet.order_by) を使用すると、値の文字列表現を使ってオブジェクトをソートします。これは、MariaDB と Oracle Database が JSON 値を同等の SQL 値に変換する関数を提供していないからです。

> **Oracle ユーザーの場合**
>
> Oracle Databaseで、 [`exclude()`](/ja/5.1/ref/models/querysets/#django.db.models.query.QuerySet.exclude) クエリ内でルックアップ値として `None` を使用すると、指定されたパスで `null` でない値を持つオブジェクト、およびパスを持たないオブジェクトが返されます。他のデータベースバックエンドでは、クエリはパスを持ち、かつ値が `null` でないオブジェクトを返します。

> **PostgreSQL の場合**
>
> PostgreSQLでは、キーやインデックスが1つしか使用されない場合、SQL演算子 `->` が使用されます。複数の演算子を使用する場合は `#>` 演算子が使用されます。

> **SQLite ユーザーの場合**
>
> SQLite では、文字列 `"true"`, `"false"`, `"null"` は常にそれぞれ `True`, `False`, JSON `null` として解釈されます。

### `contain` の概念とキーのルックアップ

#### `contains`

[`contains`](/ja/5.1/ref/models/querysets/#std-fieldlookup-contains) ルックアップは `JSONField` でオーバーライドされます。返されるオブジェクトは、与えられた `dict` キーと値のペアが、フィールドのトップレベルにすべて含まれているものです。たとえば、次のようになります:

```pycon
>>> Dog.objects.create(name="Rufus", data={"breed": "labrador", "owner": "Bob"})
<Dog: Rufus>
>>> Dog.objects.create(name="Meg", data={"breed": "collie", "owner": "Bob"})
<Dog: Meg>
>>> Dog.objects.create(name="Fred", data={})
<Dog: Fred>
>>> Dog.objects.create(
...     name="Merry", data={"breed": "pekingese", "tricks": ["fetch", "dance"]}
... )
>>> Dog.objects.filter(data__contains={"owner": "Bob"})
<QuerySet [<Dog: Rufus>, <Dog: Meg>]>
>>> Dog.objects.filter(data__contains={"breed": "collie"})
<QuerySet [<Dog: Meg>]>
>>> Dog.objects.filter(data__contains={"tricks": ["dance"]})
<QuerySet [<Dog: Merry>]>
```

> **Oracle と SQLite の場合**
>
> `JSONField` に対する `contains` ルックアップは Oracle と SQLite ではサポートされていません。

#### `contained_by`

これは [`contains`](#std-fieldlookup-jsonfield.contains) ルックアップの逆です。そのオブジェクト上のキーと値のペアが、引数で渡されたJSON値のサブセットになるようなオブジェクトを返します。例えば:

```pycon
>>> Dog.objects.create(name="Rufus", data={"breed": "labrador", "owner": "Bob"})
<Dog: Rufus>
>>> Dog.objects.create(name="Meg", data={"breed": "collie", "owner": "Bob"})
<Dog: Meg>
>>> Dog.objects.create(name="Fred", data={})
<Dog: Fred>
>>> Dog.objects.create(
...     name="Merry", data={"breed": "pekingese", "tricks": ["fetch", "dance"]}
... )
>>> Dog.objects.filter(data__contained_by={"breed": "collie", "owner": "Bob"})
<QuerySet [<Dog: Meg>, <Dog: Fred>]>
>>> Dog.objects.filter(data__contained_by={"breed": "collie"})
<QuerySet [<Dog: Fred>]>
>>> Dog.objects.filter(
...     data__contained_by={"breed": "pekingese", "tricks": ["dance", "fetch", "hug"]}
... )
<QuerySet [<Dog: Merry>, <Dog: Fred>]>
```

> **Oracle と SQLite の場合**
>
> `JSONField` に対する `contained_by` ルックアップは Oracle と SQLite ではサポートされていません。

#### `has_key`

与えられたキーがデータのトップレベルにあるオブジェクトを返します。たとえば次のようになります:

```pycon
>>> Dog.objects.create(name="Rufus", data={"breed": "labrador"})
<Dog: Rufus>
>>> Dog.objects.create(name="Meg", data={"breed": "collie", "owner": "Bob"})
<Dog: Meg>
>>> Dog.objects.filter(data__has_key="owner")
<QuerySet [<Dog: Meg>]>
```

#### `has_keys`

与えられたキーがすべて、データのトップレベルにあるオブジェクトを返します。たとえば次のようになります:

```pycon
>>> Dog.objects.create(name="Rufus", data={"breed": "labrador"})
<Dog: Rufus>
>>> Dog.objects.create(name="Meg", data={"breed": "collie", "owner": "Bob"})
<Dog: Meg>
>>> Dog.objects.filter(data__has_keys=["breed", "owner"])
<QuerySet [<Dog: Meg>]>
```

#### `has_any_keys`

与えられたキーのいずれかがデータのトップレベルにあるオブジェクトを返します。たとえば次のようになります:

```pycon
>>> Dog.objects.create(name="Rufus", data={"breed": "labrador"})
<Dog: Rufus>
>>> Dog.objects.create(name="Meg", data={"owner": "Bob"})
<Dog: Meg>
>>> Dog.objects.filter(data__has_any_keys=["owner", "breed"])
<QuerySet [<Dog: Rufus>, <Dog: Meg>]>
```

## `Q` オブジェクトを使った複雑なルックアップ

キーワード引数クエリ ([`filter()`](/ja/5.1/ref/models/querysets/#django.db.models.query.QuerySet.filter) などで使用されるもの) は "AND" 条件で結合されます。もしより複雑なクエリ（例えば、 "OR" 文を含むクエリ）を実行する必要がある場合、 [`Qオブジェクト`](/ja/5.1/ref/models/querysets/#django.db.models.Q) を使用できます。

[`Q オブジェクト`](/ja/5.1/ref/models/querysets/#django.db.models.Q) (`django.db.models.Q`) はキーワード引数のコレクションをカプセル化するためのオブジェクトです。これらのキーワード引数は上記の "フィールドルックアップ" のように指定します。

たとえば、次の `Q` オブジェクトは、1つの `LIKE` クエリをカプセル化しています。

```
from django.db.models import Q

Q(question__startswith="What")
```

`Q` オブジェクトは `&`, `|`, `^` 演算子を使って結合できます。演算子を2つの `Q` オブジェクトに使用すると、新しい `Q` オブジェクトが生成されます。

たとえば、次の文は2つの `"question__startswith"` の "OR" を表す、1つの `Q` オブジェクトを生み出します。

```
Q(question__startswith="Who") | Q(question__startswith="What")
```

このコードは次の SQL の `WHERE` 句と同等です:

```sql
WHERE question LIKE 'Who%' OR question LIKE 'What%'
```

`Q` オブジェクトと `&`, `|`, `^` 演算子を組み合わせ、括弧でグループ化することで、任意の複雑な文を作成できます。また、 `Q` オブジェクトは `~` 演算子を使用して否定することができ、通常のクエリと否定された (`NOT`) クエリの両方を組み合わせてルックアップできます:

```
Q(question__startswith="Who") | ~Q(pub_date__year=2005)
```

キーワード引数を取るルックアップ関数 (例えば [`filter()`](/ja/5.1/ref/models/querysets/#django.db.models.query.QuerySet.filter), [`exclude()`](/ja/5.1/ref/models/querysets/#django.db.models.query.QuerySet.exclude), [`get()`](/ja/5.1/ref/models/querysets/#django.db.models.query.QuerySet.get)) には、1つ以上の `Q` オブジェクトを（名前なし）位置引数として渡すこともできます。複数の `Q` オブジェクトの引数をルックアップ関数に渡すと、引数は "AND" されます。たとえば、次のようになります:

```
Poll.objects.get(
    Q(question__startswith="Who"),
    Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6)),
)
```

... これは大ざっぱにSQLに翻訳すると次のようになります:

```sql
SELECT * from polls WHERE question LIKE 'Who%'
    AND (pub_date = '2005-05-02' OR pub_date = '2005-05-06')
```

ルックアップ関数は `Q` オブジェクトとキーワード引数を混ぜて使うことができます。ルックアップ関数に提供されたすべての引数は（キーワード引数でも `Q` オブジェクトでも） "AND" で結合されます。しかし、もし `Q` オブジェクトが指定された場合は、キーワード引数の定義よりも前に指定する必要があります。たとえば次のようにします:

```
Poll.objects.get(
    Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6)),
    question__startswith="Who",
)
```

...上記は有効なクエリで、1つ前の例と同じです。しかし、:

```
# INVALID QUERY
Poll.objects.get(
    question__startswith="Who",
    Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6)),
)
```

...これは無効なクエリです。

> **See also**
>
> Django のユニットテストにある [OR ルックアップの例](https://github.com/django/django/blob/stable/5.1.x/tests/or_lookups/tests.py) は `Q` の可能な使い方をいくつか示しています。

## オブジェクトを比較する

2つのモデルインスタンスを比較するには、Pythonの標準的な比較演算子である二重の等号 `==` を使います。裏では、2つのモデルのプライマリキーの値を比較します。

上記の `Entry` を例にすると、次の2つの文は等価です:

```pycon
>>> some_entry == other_entry
>>> some_entry.id == other_entry.id
```

モデルのプライマリキーが `id` という名前でなくても問題ありません。どのような名前であっても、比較は常にプライマリキーを使用します。たとえば、モデルのプライマリキーフィールドが `name` と呼ばれている場合、これら2つの文は等価です:

```pycon
>>> some_obj == other_obj
>>> some_obj.name == other_obj.name
```

## オブジェクトを削除する

削除メソッドは便利なことに [`delete()`](/ja/5.1/ref/models/instances/#django.db.models.Model.delete) という名前です。このメソッドはオブジェクトを即座に削除し、削除されたオブジェクトの数と、オブジェクトの種類ごとの削除数を辞書として返します。例:

```pycon
>>> e.delete()
(1, {'blog.Entry': 1})
```

オブジェクトを一括で削除することもできます。すべての [`QuerySet`](/ja/5.1/ref/models/querysets/#django.db.models.query.QuerySet) は [`delete()`](/ja/5.1/ref/models/querysets/#django.db.models.query.QuerySet.delete) メソッドを持っており、その [`QuerySet`](/ja/5.1/ref/models/querysets/#django.db.models.query.QuerySet) のすべてのメンバーを削除します。

たとえば、これは `pub_date` が2005年の `Entry` オブジェクトをすべて削除します:

```pycon
>>> Entry.objects.filter(pub_date__year=2005).delete()
(5, {'webapp.Entry': 5})
```

これは可能な限り純粋にSQLで実行されます。そのため、処理中に個々のオブジェクトインスタンスの `delete()` メソッドが呼び出される必要はないことに注意してください。もしあなたが独自の `delete()` メソッドをモデルクラスに定義しており、それを確実に呼び出したい場合は、[`QuerySet`](/ja/5.1/ref/models/querysets/#django.db.models.query.QuerySet) の [`delete()`](/ja/5.1/ref/models/querysets/#django.db.models.query.QuerySet.delete) メソッドを使って一括削除するのではなく、「手動で」そのモデルインスタンスを削除する必要があります（たとえば、 QuerySet をイテレートして各オブジェクトに対し個別に `delete()` を呼び出します）。

Django がオブジェクトを削除するとき、デフォルトでは SQL の制約 `ON DELETE CASCADE` の動作をエミュレートします。言い換えると、削除するオブジェクトを指している外部キーを持つすべてのオブジェクトは、ともに削除されます。たとえば、

```
b = Blog.objects.get(pk=1)
# This will delete the Blog and all of its Entry objects.
b.delete()
```

このカスケード動作は、[`ForeignKey`](/ja/5.1/ref/models/fields/#django.db.models.ForeignKey) の [`on_delete`](/ja/5.1/ref/models/fields/#django.db.models.ForeignKey.on_delete) 引数でカスタマイズできます。

注意点として、 [`delete()`](/ja/5.1/ref/models/querysets/#django.db.models.query.QuerySet.delete) は、 [`QuerySet`](/ja/5.1/ref/models/querysets/#django.db.models.query.QuerySet) メソッドの中で唯一、 [`Manager`](/ja/5.1/topics/db/managers/#django.db.models.Manager) 自身からは公開されていません。これは、誤って `Entry.objects.delete()` を呼び出して *すべての* エントリを削除してしまわないようにするための安全対策です。もしあなたが *本当に* すべてのオブジェクトを削除したい場合は、下記のように明示的に完全なクエリセットに対して呼び出す必要があります。

```
Entry.objects.all().delete()
```

## モデルのインスタンスを複製する

モデルインスタンスをコピーする組み込みメソッドはありませんが、全てのフィールドの値をコピーした新しいインスタンスは簡単に作ることができます。最も単純なケースでは、 `pk` を `None` に設定し、 [`_state.adding`](/ja/5.1/ref/models/instances/#django.db.models.Model._state) を `True` に設定します。ブログの例で説明すると、次のようになります:

```
blog = Blog(name="My blog", tagline="Blogging is easy")
blog.save()  # blog.pk == 1

blog.pk = None
blog._state.adding = True
blog.save()  # blog.pk == 2
```

継承を使っている場合、もっと複雑になります。`Blog` のサブクラスを考えると:

```
class ThemeBlog(Blog):
    theme = models.CharField(max_length=200)

django_blog = ThemeBlog(name="Django", tagline="Django is easy", theme="python")
django_blog.save()  # django_blog.pk == 3
```

継承のしくみ上、`pk` と `id` の両方を `None` に設定し、 `_state.adding` を `True` に設定する必要があります:

```
django_blog.pk = None
django_blog.id = None
django_blog._state.adding = True
django_blog.save()  # django_blog.pk == 4
```

この処理では、モデルのデータベーステーブルの一部ではないリレーションは複製しません。例えば、`Entry` は `Author` への `ManyToManyField` を持ちます。entry の複製後、新しい entry に対して多対多のリレーションをセットする必要があります:

```
entry = Entry.objects.all()[0]  # some previous entry
old_authors = entry.authors.all()
entry.pk = None
entry._state.adding = True
entry.save()
entry.authors.set(old_authors)
```

`OneToOneField` については、1 対 1 のユニーク制約への違反を避けるため、リレーション先オブジェクトを複製して新しいオブジェクトのフィールドに割り当てる必要があります。たとえば上記のように `entry` がすでに複製されている場合、次のようにします。

```
detail = EntryDetail.objects.all()[0]
detail.pk = None
detail._state.adding = True
detail.entry = entry
detail.save()
```

## 複数のオブジェクトを一括で更新する

[`QuerySet`](/ja/5.1/ref/models/querysets/#django.db.models.query.QuerySet) のすべてのオブジェクトに、特定の値をセットしたい場合があります。[`update()`](/ja/5.1/ref/models/querysets/#django.db.models.query.QuerySet.update) を使えば実現できます。例えば:

```
# Update all the headlines with pub_date in 2007.
Entry.objects.filter(pub_date__year=2007).update(headline="Everything is the same")
```

このメソッドを使ってセットできるのは非リレーションフィールドと [`ForeignKey`](/ja/5.1/ref/models/fields/#django.db.models.ForeignKey) フィールドのみです。非リレーションフィールドを更新するには、新しい値を定数として渡します。 [`ForeignKey`](/ja/5.1/ref/models/fields/#django.db.models.ForeignKey) フィールドを更新するには、結び付けたい新しいモデルインスタンスを新しい値にセットしてください。たとえば、次のようにします:

```pycon
>>> b = Blog.objects.get(pk=1)

# Change every Entry so that it belongs to this Blog.
>>> Entry.objects.update(blog=b)
```

`update()` は即座に適用され、クエリにマッチした行数を返します (行はすでに新しい値を持っていることがあるので、更新された行の数と一致するとは限りません)。更新する [`QuerySet`](/ja/5.1/ref/models/querysets/#django.db.models.query.QuerySet) の唯一の制限は、1 つのデータベーステーブル (モデルのメインテーブル) にしかアクセスできないことです。リレーション先のフィールドでフィルタすることもできますが、モデルのメインテーブルのカラムしか更新できません。例えば:

```pycon
>>> b = Blog.objects.get(pk=1)

# Update all the headlines belonging to this Blog.
>>> Entry.objects.filter(blog=b).update(headline="Everything is the same")
```

`update()` は直接 SQL文に変換されることに注意してください。これは、直接更新する一括操作です。 [`save()`](/ja/5.1/ref/models/instances/#django.db.models.Model.save) を実行することは一切なく、([`save()`](/ja/5.1/ref/models/instances/#django.db.models.Model.save) を呼び出した結果である) `pre_save` や `post_save` のシグナルも出しません。 [`auto_now`](/ja/5.1/ref/models/fields/#django.db.models.DateField.auto_now) フィールドオプションも実施しません。 [`QuerySet`](/ja/5.1/ref/models/querysets/#django.db.models.query.QuerySet) のすべてのアイテムを保存し、各インスタンスで [`save()`](/ja/5.1/ref/models/instances/#django.db.models.Model.save) メソッドが確実に呼ばれるようにしたい場合、特別な機能は不要です。これらをループし、 [`save()`](/ja/5.1/ref/models/instances/#django.db.models.Model.save) を呼び出してください:

```
for item in my_queryset:
    item.save()
```

update の呼び出しでは、 [`F 式`](/ja/5.1/ref/models/expressions/#django.db.models.F) を使ってモデル内の別のフィールドの値に基づいてフィールドを更新することもできます。これは、現在値に基づいてカウンタを増加させる場合に特に有用です。例えば、ブログの各 entry の pingback カウントを増加させるには:

```pycon
>>> Entry.objects.update(number_of_pingbacks=F("number_of_pingbacks") + 1)
```

しかし、filter および exclude 句での `F()` オブジェクトとは異なり、update で `F()` オブジェクトを使うときはテーブル結合はできません。できるのは、更新されるモデルに関係付けられたフィールドを参照することだけです。 `F()` オブジェクト内でテーブル結合が必要なルックアップを行おうとすると、 `FieldError` が送出されます。

```pycon
# This will raise a FieldError
>>> Entry.objects.update(headline=F("blog__name"))
```

## リレーション先のオブジェクト

モデルでリレーションシップを定義した場合 (例えば [`ForeignKey`](/ja/5.1/ref/models/fields/#django.db.models.ForeignKey)、[`OneToOneField`](/ja/5.1/ref/models/fields/#django.db.models.OneToOneField)、[`ManyToManyField`](/ja/5.1/ref/models/fields/#django.db.models.ManyToManyField) の 3 つです)、そのモデルのインスタンスはリレーション先のオブジェクトにアクセスするための便利な API を持ちます。

このページで最初に提示したモデルを使うと、例えば、`Entry` オブジェクト `e` は、`blog` 属性 (`e.blog`) にアクセスすることで、関連付けられた `Blog` オブジェクトを得ることができます。

(裏では、この機能は Python [descriptors](https://docs.python.org/3/howto/descriptor.html) によって実装されています。これはとくに重要ではありませんが、興味がある人のためにここに書いておきます)。

Djangoは、リレーションシップの「反対」側のためのAPIアクセサも作成します。関連付けられた相手のモデルから、リレーションシップが定義されている元のモデルへのリンクです。たとえば、`Blog` オブジェクト `b` は、関連付けられたすべての `Entry` オブジェクトに対するリンクを、`entry_set` 属性を通じて、`b.entry_set.all()` のようにアクセスできます。

このセクションのすべての例で使われたサンプルの `Blog`、`Author`、`Entry` モデルは、このページの最初で定義したものです。

### 一対多のリレーションシップ

#### 順方向のアクセス

モデルに [`ForeignKey`](/ja/5.1/ref/models/fields/#django.db.models.ForeignKey) がある場合、そのモデルのインスタンスは、モデルの属性を介してリレーション先の（外部）オブジェクトにアクセスできます。

例:

```pycon
>>> e = Entry.objects.get(id=2)
>>> e.blog  # Returns the related Blog object.
```

外部キー属性を介して値を取得したりセットしたりできます。他の例と同様、外部キーの変更は次のように [`save()`](/ja/5.1/ref/models/instances/#django.db.models.Model.save) を呼び出すまでデータベースには保存されません。

```pycon
>>> e = Entry.objects.get(id=2)
>>> e.blog = some_blog
>>> e.save()
```

[`ForeignKey`](/ja/5.1/ref/models/fields/#django.db.models.ForeignKey) フィールドに `null=True` が設定されている場合 (つまり、 `NULL` 値を許可している場合)、次のように、 `None` を代入することでリレーションを削除できます。

```pycon
>>> e = Entry.objects.get(id=2)
>>> e.blog = None
>>> e.save()  # "UPDATE blog_entry SET blog_id = NULL ...;"
```

一対多のリレーションシップへの順方向のアクセスは、リレーション先オブジェクトに最初にアクセスしたときにキャッシュされます。同じオブジェクトインスタンスの外部キーへのその後のアクセスはキャッシュされます。例えば次のコードはキャッシュを使います。

```pycon
>>> e = Entry.objects.get(id=2)
>>> print(e.blog)  # Hits the database to retrieve the associated Blog.
>>> print(e.blog)  # Doesn't hit the database; uses cached version.
```

[`QuerySet`](/ja/5.1/ref/models/querysets/#django.db.models.query.QuerySet) のメソッドである [`select_related()`](/ja/5.1/ref/models/querysets/#django.db.models.query.QuerySet.select_related) は、全ての一対多のリレーションシップのキャッシュを再帰的に先読みします。たとえば次のようになります。

```pycon
>>> e = Entry.objects.select_related().get(id=2)
>>> print(e.blog)  # Doesn't hit the database; uses cached version.
>>> print(e.blog)  # Doesn't hit the database; uses cached version.
```

#### "逆方向" のリレーションシップ

モデルが [`ForeignKey`](/ja/5.1/ref/models/fields/#django.db.models.ForeignKey) を持つ場合、外部キーのモデルのインスタンスは最初のモデルのインスタンスを返す [`Manager`](/ja/5.1/topics/db/managers/#django.db.models.Manager) にアクセスできます。デフォルトでは、この [`Manager`](/ja/5.1/topics/db/managers/#django.db.models.Manager) は `FOO_set` と名付けられており、`FOO` には元のモデル名が小文字で入ります。この [`Manager`](/ja/5.1/topics/db/managers/#django.db.models.Manager) は `QuerySets` を返し、上述の "オブジェクトを取り出す" セクションで説明したようにフィルタおよび操作が可能です。

例:

```pycon
>>> b = Blog.objects.get(id=1)
>>> b.entry_set.all()  # Returns all Entry objects related to Blog.

# b.entry_set is a Manager that returns QuerySets.
>>> b.entry_set.filter(headline__contains="Lennon")
>>> b.entry_set.count()
```

[`ForeignKey`](/ja/5.1/ref/models/fields/#django.db.models.ForeignKey) 定義の [`related_name`](/ja/5.1/ref/models/fields/#django.db.models.ForeignKey.related_name) パラメータを指定することで、 `FOO_set` の名前を上書きできます。たとえば、 `Entry` モデルを `blog = ForeignKey(Blog, on_delete=models.CASCADE, related_name='entries')` に変更した場合、上記のコード例は次のようになります:

```pycon
>>> b = Blog.objects.get(id=1)
>>> b.entries.all()  # Returns all Entry objects related to Blog.

# b.entries is a Manager that returns QuerySets.
>>> b.entries.filter(headline__contains="Lennon")
>>> b.entries.count()
```

#### カスタムのリバースマネージャを使う

デフォルトでは、逆方向のリレーションシップに使われる [`RelatedManager`](/ja/5.1/ref/models/relations/#django.db.models.fields.related.RelatedManager) はモデルに対する [デフォルト マネージャ](/ja/5.1/topics/db/managers/#manager-names) のサブクラスです。与えられたクエリに対して別のマネージャを指定したい場合、以下の構文が使用できます:

```
from django.db import models

class Entry(models.Model):
    # ...
    objects = models.Manager()  # Default Manager
    entries = EntryManager()  # Custom Manager

b = Blog.objects.get(id=1)
b.entry_set(manager="entries").all()
```

`EntryManager` が、`get_queryset()` メソッドでデフォルトのフィルタ動作をした場合、`all()` の呼び出しに適用されます。

カスタムリバースマネージャを指定すると、そのカスタムメソッドを呼び出すこともできます:

```
b.entry_set(manager="entries").is_published()
```

> **プリフェッチ（先読み）との関係**
>
> 逆リレーションを指定して [`prefetch_related()`](/ja/5.1/ref/models/querysets/#django.db.models.query.QuerySet.prefetch_related) をコールすると、 デフォルトのマネージャが使用されます。カスタムのリバースマネージャを使用して リレーション先のオブジェクトをプリフェッチしたい場合は、 [`Prefetch()`](/ja/5.1/ref/models/querysets/#django.db.models.Prefetch) を使用します。たとえば次のようになります:
>
> ```
> from django.db.models import Prefetch
>
> prefetch_manager = Prefetch("entry_set", queryset=Entry.entries.all())
> Blog.objects.prefetch_related(prefetch_manager)
> ```

#### リレーション先オブジェクトを処理する他のメソッド

上述の "オブジェクトを取り出す" で定義した [`QuerySet`](/ja/5.1/ref/models/querysets/#django.db.models.query.QuerySet) メソッドに加えて、[`ForeignKey`](/ja/5.1/ref/models/fields/#django.db.models.ForeignKey) [`Manager`](/ja/5.1/topics/db/managers/#django.db.models.Manager) はリレーション先オブジェクトのセットを処理するために使われる他のメソッドを持っています。それぞれの概略は以下の通りです。完全な詳細は [リレーション先オブジェクトのリファレンス](/ja/5.1/ref/models/relations/) で確認できます。

**`add(obj1, obj2, ...)`**

  指定したモデルオブジェクトをリレーション先オブジェクトのセットに追加します。

**`create(**kwargs)`**

  新しいオブジェクトを作成、保存して、リレーション先オブジェクトのセットに格納します。新しく作成されたオブジェクトを返します。

**`remove(obj1, obj2, ...)`**

  リレーション先オブジェクトのセットから、指定したモデルオブジェクトを削除します。

**`clear()`**

  リレーション先オブジェクトのセットからすべてのオブジェクトを削除します。

**`set(objs)`**

  リレーション先オブジェクトのセットを置き換えます。

リレーション先のセットのメンバーを代入するには、オブジェクトインスタンスのイテラブルとともに `set()` メソッドを使ってください。 例えば、`e1` と `e2` が `Entry` のインスタンスだとして:

```
b = Blog.objects.get(id=1)
b.entry_set.set([e1, e2])
```

もし `clear()` メソッドが利用可能なら、既存のオブジェクトは `entry_set` から削除された後、イテラブル (この場合はリスト) のすべてのオブジェクトがセットに追加されます。もし `clear()` メソッドが利用可能 *でない* 場合は、既存の要素を削除することなく、イテラブル内のすべてのオブジェクトが追加されます。

このセクションで説明した "逆方向" の操作は、すべて即座にデータベースに反映されます。すべての追加、作成、削除の操作は自動的にデータベースに保存されます。

### 多対多 (many-to-many) 関係

多対多リレーションシップの両方の側で、もう片方に対する自動的な API アクセスを使えます。API は、上述の "逆方向" の1 対多リレーションシップと似た形で動作します。

一つの違いは属性の命名です。 [`ManyToManyField`](/ja/5.1/ref/models/fields/#django.db.models.ManyToManyField) を定義するモデルでは、そのフィールドの属性名そのものを使いますが、"逆" モデルでは元のモデルの小文字のモデル名に `'_set'` を加えたものを使います (逆の一対多リレーションシップと同じです)。

例を挙げるとわかりやすいでしょう:

```
e = Entry.objects.get(id=3)
e.authors.all()  # Returns all Author objects for this Entry.
e.authors.count()
e.authors.filter(name__contains="John")

a = Author.objects.get(id=5)
a.entry_set.all()  # Returns all Entry objects for this Author.
```

[`ForeignKey`](/ja/5.1/ref/models/fields/#django.db.models.ForeignKey) と同様に、[`ManyToManyField`](/ja/5.1/ref/models/fields/#django.db.models.ManyToManyField) も [`related_name`](/ja/5.1/ref/models/fields/#django.db.models.ManyToManyField.related_name) を指定できます。上記の例で、もし `Entry` の [`ManyToManyField`](/ja/5.1/ref/models/fields/#django.db.models.ManyToManyField) が `related_name='entries'` を指定していた場合、各 `Author` インスタンスは `entry_set` の代わりに `entries` 属性を持つことになります。

一対多のリレーションシップとのもう一つの違いは、モデルインスタンスに加えて、多対多のリレーションシップの `add()`, `set()`, `remove()` メソッドでもプライマリキーの値を受け付けることです。たとえば、 `e1` と `e2` が `Entry` インスタンスである場合、これらの `set()` 呼び出しは同じように動作します:

```
a = Author.objects.get(id=5)
a.entry_set.set([e1, e2])
a.entry_set.set([e1.pk, e2.pk])
```

### 一対一 (one-to-one) 関係

一対一のリレーションシップは多対一のリレーションシップとよく似ています。モデルに [`OneToOneField`](/ja/5.1/ref/models/fields/#django.db.models.OneToOneField) を定義すると、そのモデルのインスタンスはモデルの属性を介してリレーション先オブジェクトにアクセスできるようになります。

例:

```
class EntryDetail(models.Model):
    entry = models.OneToOneField(Entry, on_delete=models.CASCADE)
    details = models.TextField()

ed = EntryDetail.objects.get(id=2)
ed.entry  # Returns the related Entry object.
```

違いは "逆" クエリにあります。一対一のリレーション先モデルも [`Manager`](/ja/5.1/topics/db/managers/#django.db.models.Manager) オブジェクトにアクセスできますが、 [`Manager`](/ja/5.1/topics/db/managers/#django.db.models.Manager) はオブジェクトのコレクションではなく、単一のオブジェクトを表します：

```
e = Entry.objects.get(id=2)
e.entrydetail  # returns the related EntryDetail object
```

このリレーションシップにオブジェクトが割り当てられていない場合、 Django は `DoesNotExist` 例外を発生させます。

インスタンスは、順方向のリレーションシップを割り当てるのと同じ方法で、逆方向のリレーションシップに割り当てることができます:

```
e.entrydetail = ed
```

### どうやって逆方向のリレーションシップを実現しているのか？

他のオブジェクトリレーショナルマッパでは、リレーションシップを両サイドで定義する必要があります。Django の開発陣はこれは DRY (Don't Repeat Yourself) の原則に反していると考えており、Django では片側でリレーションシップを定義する必要があるだけとなりました。

しかし、どのようにして実現しているのでしょうか? モデルクラスは、他のどのモデルクラスと関係しているのか、関係先のモデルクラスが読み込まれるまで分からないはずです。

答えは [`アプリレジストリ`](/ja/5.1/ref/applications/#django.apps.apps) にあります。Djangoが起動すると、[`INSTALLED_APPS`](/ja/5.1/ref/settings/#std-setting-INSTALLED_APPS) に記載された各アプリケーションをインポートし、その後各アプリケーション内の `models` モジュールをインポートします。新しいモデルクラスが作成されるたびに、Djangoは関連するモデルに逆方向のリレーションシップを追加します。リレーション先のモデルがまだインポートされていない場合、Djangoはこのリレーションシップを追跡し、リレーション先のモデルが最終的にインポートされたときにそれらを追加します。

この理由により、[`INSTALLED_APPS`](/ja/5.1/ref/settings/#std-setting-INSTALLED_APPS) にリストアップするアプリケーション内に、使おうとしているモデルをすべて定義することが特に重要となります。そうしないと、逆方向のリレーションシップがうまく動作しなくなります。

### リレーション先オブジェクトをまたいだクエリ

リレーション先オブジェクトを含むクエリは、通常の値フィールドを含むクエリと同じルールに従います。クエリにマッチするための値を指定する際、オブジェクトインスタンス自体かオブジェクトのプライマリキー値のどちらかを使用します。

例えば、`id=5` の Blog オブジェクト `b` がある場合、以下の 3 つのクエリは同一となります:

```
Entry.objects.filter(blog=b)  # Query using object instance
Entry.objects.filter(blog=b.id)  # Query using id from instance
Entry.objects.filter(blog=5)  # Query using id directly
```

## 素の SQL にフォールバックする

Django のデータベースマッパが扱うには複雑すぎる SQL クエリを記述する必要がある場合、手書きで SQL を書くことができます。Django には、素の SQL クエリを記述するための方法がいくつかあります。詳しくは [素の SQL 文の実行](/ja/5.1/topics/db/sql/) を参照してください。

最後に、覚えておいてほしい重要な点は、Django のデータベースレイヤはあなたのデータベースに対する単なるインターフェースでしかないということです。あなたは、他のツール、プログラミング言語、データベースフレームワークなどを通じてデータベースを操作することもできます。データベースに関して Django 特有のことは何もありません。
