---
title: "クエリ式 (Query Expression)"
version: 6.1
locale: ja
source: https://docs.djangoproject.com/ja/6.1/ref/models/expressions/
canonical: https://djangodocs.dev/ja/6.1/ref/models/expressions/
---
# クエリ式 (Query Expression)

クエリ式 (query expression) は、update、create、filter、order by、annotation、またはaggregateの一部として使用できる値または計算を記述します。式が真偽値を出力する場合、フィルタで直接使用できます。クエリの記述に使用できる組み込みの式 (expression) は多数あります (以下で説明します)。式を組み合わせたり、場合によっては入れ子にしてより複雑な計算を行うこともできます。

## サポートされている算術演算

Django は Python の定数や変数、そして他の式を使って、クエリ式での否定、 加算、減算、乗算、除算、モジュロ演算、そしてべき乗演算をサポートします。

## 出力フィールド (`output_field`)

このセクションで説明する式の多くは、オプションの `output_field` パラメータをサポートしています。指定された場合、 Django はデータベースから値を取得した後、そのフィールドに値を読み込みます。

`output_field` は `IntegerField()` や `BooleanField()` のようなモデルフィールドのインスタンスを取ります。通常、フィールドには `max_length` のような引数は不要です。フィールドの引数はデータの検証に関連しており、その検証は式の出力値に対して実行されないからです。

`output_field` が必要なのは、フィールド型が混在する複雑な式のように、 Django が結果のフィールド型を自動的に判断できない場合だけです。例えば、 `DecimalField()` と `FloatField()` を足す場合、 `output_field=FloatField()` のように出力フィールドが必要になります。

`output_field` では、特定のモデルフィールドの文脈に依存せず、型変換を行うカスタムフィールドを使用することもできます。たとえば、 `timedelta` を使った日付計算を頻繁に行う場合、その変換処理を担当するカスタムフィールドを作成することで、データベース間で一貫した結果を得やすくなります。詳しくは [カスタムのモデルフィールドを作成する](/ja/6.1/howto/custom-model-fields/) を参照してください。

## 例

```pycon
>>> from django.db.models import Count, F, Value
>>> from django.db.models.functions import Length, Upper
>>> from django.db.models.lookups import GreaterThan

# Find companies that have more employees than chairs.
>>> Company.objects.filter(num_employees__gt=F("num_chairs"))

# Find companies that have at least twice as many employees
# as chairs. Both the querysets below are equivalent.
>>> Company.objects.filter(num_employees__gt=F("num_chairs") * 2)
>>> Company.objects.filter(num_employees__gt=F("num_chairs") + F("num_chairs"))

# How many chairs are needed for each company to seat all employees?
>>> company = (
...     Company.objects.filter(num_employees__gt=F("num_chairs"))
...     .annotate(chairs_needed=F("num_employees") - F("num_chairs"))
...     .first()
... )
>>> company.num_employees
120
>>> company.num_chairs
50
>>> company.chairs_needed
70

# Create a new company using expressions.
>>> company = Company.objects.create(name="Google", ticker=Upper(Value("goog")))
>>> company.ticker
'GOOG'

# Annotate models with an aggregated value. Both forms
# below are equivalent.
>>> Company.objects.annotate(num_products=Count("products"))
>>> Company.objects.annotate(num_products=Count(F("products")))

# Aggregates can contain complex computations also
>>> Company.objects.annotate(num_offerings=Count(F("products") + F("services")))

# Expressions can also be used in order_by(), either directly
>>> Company.objects.order_by(Length("name").asc())
>>> Company.objects.order_by(Length("name").desc())
# or using the double underscore lookup syntax.
>>> from django.db.models import CharField
>>> from django.db.models.functions import Length
>>> CharField.register_lookup(Length)
>>> Company.objects.order_by("name__length")

# Boolean expression can be used directly in filters.
>>> from django.db.models import Exists, OuterRef
>>> Company.objects.filter(
...     Exists(Employee.objects.filter(company=OuterRef("pk"), salary__gt=10))
... )

# Lookup expressions can also be used directly in filters
>>> Company.objects.filter(GreaterThan(F("num_employees"), F("num_chairs")))
# or annotations.
>>> Company.objects.annotate(
...     need_chairs=GreaterThan(F("num_employees"), F("num_chairs")),
... )
```

## 組み込みのクエリ式

> **Note**
>
> これらの式は `django.db.models.expressions` と `django.db.models.aggregates` で定義されていますが、利便性のために [`django.db.models`](/ja/6.1/topics/db/models/#module-django.db.models) からインポートできます。

### `F()` 式

#### `class F`

`F()` オブジェクトはモデルフィールドの値、モデルフィールドを変換した値、アノテーションを付けた列を表します。これを使うことで、実際にデータベースから Python のメモリに取り出さずに、モデルフィールドの値を参照してデータベース操作を行うことができます。

代わりに、 Django は `F()` オブジェクトを使って、データベースレベルで必要な操作を記述する SQL 式を生成します。

例でやってみましょう。通常はこのようにします：

```
# Tintin filed a news story!
reporter = Reporters.objects.get(name="Tintin")
reporter.stories_filed += 1
reporter.save()
```

ここでは、`reporter.stories_filed` の値をデータベースからメモリに取り込んで、Pythonでおなじみの演算子を使って操作し、そのオブジェクトをデータベースに保存しています。しかし、代わりに次のようにすることもできます：

```
from django.db.models import F

reporter = Reporters.objects.get(name="Tintin")
reporter.stories_filed = F("stories_filed") + 1
reporter.save()
```

`reporter.stories_filed = F('stories_filed') + 1` はインスタンス属性に値を代入する普通の Python 構文のように見えますが、実際にはデータベースに対する操作を記述するSQL構文です。

Djangoが `F()` インスタンスを見つけると、標準のPython演算子をオーバーライドしてカプセル化されたSQL式を作成します。この場合、`reporter.stories_filed` によって表されるデータベースフィールドをインクリメントするようにデータベースに指示する式が作成されます。

`reporter.stories_filed` にどんな値があったとしても、Pythonはそれを知ることはありません。それは完全にデータベースが扱います。Python が Django の `F()` クラスを通して行うことは、フィールドを参照し、処理を記述する SQL 構文を作成することだけです。

As well as being used in operations on single instances as above, `F()` can
be used with `update()` to perform bulk updates on a `QuerySet`. This
reduces the two queries we were using above - the `get()` and the
[`save()`](/ja/6.1/ref/models/instances/#django.db.models.Model.save) \- to just one:

```
reporter = Reporters.objects.filter(name="Tintin")
reporter.update(stories_filed=F("stories_filed") + 1)
```

We can also use [`update()`](/ja/6.1/ref/models/querysets/#django.db.models.query.QuerySet.update) to increment
the field value on multiple objects - which could be very much faster than
pulling them all into Python from the database, looping over them, incrementing
the field value of each one, and saving each one back to the database:

```
Reporter.objects.update(stories_filed=F("stories_filed") + 1)
```

つまり、`F()` は、以下のようなパフォーマンス上の利点があります：

- 作業をPythonではなく、データベースに行わせること
- 一部の操作に必要なクエリの数を減らすこと

#### `F()` 式のスライス

文字列ベースのフィールド、テキストベースのフィールド、および [`ArrayField`](/ja/6.1/ref/contrib/postgres/fields/#django.contrib.postgres.fields.ArrayField) では、Python の配列スライス構文が使用できます。インデックスは0から始まります。 `slice` の `step` 引数と、負のインデックスはサポートされていません。例えば、次のように記述できます：

```pycon
>>> # Replacing a name with a substring of itself.
>>> writer = Writers.objects.get(name="Priyansh")
>>> writer.name = F("name")[1:5]
>>> writer.save()
>>> writer.name
'riya'
```

#### `F()` を使った競合状態の回避

`F()` のもう一つの便利な利点は、Pythonではなくデータベースがフィールドの値を更新することで *競合状態* を避けることができるということです。

2つのPythonスレッドが上記の最初の例のコードを実行した場合、1つのスレッドはもう1つのスレッドがデータベースから値を取得した後にフィールドの値を取得、インクリメント、保存する可能性があります。2番目のスレッドが保存する値は元の値に基づいています。

If the database is responsible for updating the field, the process is more
robust: it will only ever update the field based on the value of the field in
the database when the [`save()`](/ja/6.1/ref/models/instances/#django.db.models.Model.save) or `update()` is executed, rather
than based on its value when the instance was retrieved.

#### `F()` assignments are refreshed after `Model.save()`

`F()` objects assigned to model fields are refreshed from the database on
[`save()`](/ja/6.1/ref/models/instances/#django.db.models.Model.save) on backends that support it without incurring a subsequent
query (SQLite, PostgreSQL, and Oracle) and deferred otherwise (MySQL or
MariaDB). For example:

```pycon
>>> reporter = Reporters.objects.get(name="Tintin")
>>> reporter.stories_filed = F("stories_filed") + 1
>>> reporter.save()
>>> reporter.stories_filed  # This triggers a refresh query on MySQL/MariaDB.
14  # Assuming the database value was 13 when the object was saved.
```

> **Changed in Django 6.0**
>
> In previous versions of Django, `F()` objects were not refreshed from the
> database on [`save()`](/ja/6.1/ref/models/instances/#django.db.models.Model.save) which resulted in them being evaluated and
> persisted every time the instance was saved.

#### フィルタで `F()` を使う

`F()` は `QuerySet` フィルタでも非常に有用で、Python の値ではなく、フィールドの値に基づいてオブジェクトをフィルタリングできます。

これは [クエリで F() 式を使う](/ja/6.1/topics/db/queries/#using-f-expressions-in-filters) で説明されています。

#### `F()` をアノテーションと一緒に使う

`F()` を使うと、算術演算で異なるフィールドを組み合わせてモデルに動的なフィールドを作成できます：

```
company = Company.objects.annotate(chairs_needed=F("num_employees") - F("num_chairs"))
```

組み合わせるフィールドの型が異なる場合、どのようなフィールドが返されるかを Django に伝える必要があります。ほとんどの式は [output\_field](#output-field) をサポートしていますが、 `F()` はサポートしていないので、 [`ExpressionWrapper`](#django.db.models.ExpressionWrapper) で式をラップする必要があります：

```
from django.db.models import DateTimeField, ExpressionWrapper, F

Ticket.objects.annotate(
    expires=ExpressionWrapper(
        F("active_at") + F("duration"), output_field=DateTimeField()
    )
)
```

`ForeignKey` のようなリレーション先フィールドを参照する場合、 `F()` はモデルインスタンスではなく主キーの値を返します：

```pycon
>>> car = Company.objects.annotate(built_by=F("manufacturer"))[0]
>>> car.manufacturer
<Manufacturer: Toyota>
>>> car.built_by
3
```

#### NULL 値のソートに `F()` を使う

`F()` と [`Expression.asc()`](#django.db.models.Expression.asc) または [`desc()`](#django.db.models.Expression.desc) のキーワード引数 `nulls_first` または `nulls_last` を使用して、フィールドの null 値のソートの順序を制御します。デフォルトでは、ソートの順序はデータベースに依存します。

例えば、まだコンタクトしていない企業 (`last_contacted` がNULL) をコンタクトした企業の後に並べるには次のようにします：

```
from django.db.models import F

Company.objects.order_by(F("last_contacted").desc(nulls_last=True))
```

#### 論理演算で `F()` を使う

`BooleanField` を出力する `F()` 式は反転演算子 `~F()` で論理的に否定することができます。たとえば企業の is\_active ステータスを反転する場合、以下のようにします：

```
from django.db.models import F

Company.objects.update(is_active=~F("is_active"))
```

### `Func()` 式

`Func()` 式は `COALESCE` や `LOWER` のようなデータベース関数や、 `SUM` のような集計を含むすべての式の基本型です。これらは直接使用できます：

```
from django.db.models import F, Func

queryset.annotate(field_lower=Func(F("field"), function="LOWER"))
```

または、データベース関数のライブラリを構築するためにも使用できます：

```
class Lower(Func):
    function = "LOWER"

queryset.annotate(field_lower=Lower("field"))
```

しかし、どちらの場合も、モデルが追加の属性 `field_lower` でアノテーションされたクエリセットを生成します。この属性は、大まかには次のSQLから生成されます：

```sql
SELECT
    ...
    LOWER("db_table"."field") as "field_lower"
```

See [データベース関数](/ja/6.1/ref/models/database-functions/) for a list of built-in database
functions.

`Func` のAPI は以下の通りです：

#### `class Func(*expressions, **extra)`

#### `function`

生成する関数を指定するクラス属性です。具体的には、 `function` が [`template`](#django.db.models.Func.template) 内の `function` プレースホルダとして補間されます。デフォルトは `None` です。

#### `template`

この関数に対して生成される SQL を記述する、フォーマット文字列としてのクラス属性です。デフォルトは `'%(function)s(%(expressions)s)'` です。

`strftime('%W','date')` のようなSQLを作成していて、クエリでリテラル文字 `%` が必要な場合は、`template` 属性では `%%%%` と4倍にしてください。文字列は `as_sql()` でのテンプレート補間と、データベースカーソルでのクエリパラメータによるSQL補間の2回補間されるからです。

#### `arg_joiner`

クラス属性は `expressions` のリストを結合するために使用される文字を表します。デフォルトは `', '` です。

#### `arity`

関数が受け付ける引数の数を表すクラス属性です。この属性が設定されていて、関数が異なる数の式で呼び出された場合、 `TypeError` が発生します。デフォルトは `None` です。

#### `as_sql(compiler, connection, function=None, template=None, arg_joiner=None, **extra_context)`

データベース関数の SQL フラグメントを生成します。タプル `(sql, params)` を返します。`sql` は SQL 文字列で、`params` はクエリパラメータのリストまたはタプルです。

`as_vendor()` メソッドは、`function`, `template`, `arg_joiner` およびその他の `**extra_context` パラメータを使用して、必要に応じてSQLをカスタマイズするべきです。例えば：

*`django/db/models/functions.py`*

```python
class ConcatPair(Func):
    ...
    function = "CONCAT"
    ...

    def as_mysql(self, compiler, connection, **extra_context):
        return super().as_sql(
            compiler,
            connection,
            function="CONCAT_WS",
            template="%(function)s('', %(expressions)s)",
            **extra_context
        )
```

SQL インジェクションの脆弱性を回避するために、`extra_context` は [信頼できないユーザー入力を含んではいけません](#avoiding-sql-injection-in-query-expressions) 。これらの値はデータベースドライバによってエスケープされるクエリパラメータとして渡されるのではなく、SQL文字列に補間されるからです。

引数 `*expressions` は関数が適用される位置引数としての式のリストです。式は文字列に変換され、 `arg_joiner` で連結された後、 `expressions` プレースホルダとして `template` に挿入されます。

位置引数には式か Python の値を指定できます。文字列はカラム参照とみなされ、 `F()` 式でラップされ、その他の値は `Value()` 式でラップされます。

`*extra` kwargs は `template` 属性に補間できる `key=value` のペアです。SQL インジェクションの脆弱性を回避するために、`*extra` は [信頼できないユーザー入力を含んではいけません](#avoiding-sql-injection-in-query-expressions) 。これらの値はデータベースドライバによってエスケープされるクエリパラメータとして渡されるのではなく、SQL文字列に補間されるからです。

`function`, `template`, および `arg_joiner` キーワードは、同じ名前の属性を置き換えるために使用でき、独自のクラスを定義する必要はありません。[output\_field](#output-field) は、期待される戻り値の型を定義するために使用できます。

> **Sanitize input used to configure a query expression**
>
> Built-in database functions (such as
> [`Cast`](/ja/6.1/ref/models/database-functions/#django.db.models.functions.Cast)) vary in whether arguments such
> as `output_field` can be supplied as positional arguments or only by
> keyword. For `output_field` and several other cases, the input ultimately
> reaches `Func()` as a keyword argument, so the advice to avoid
> constructing keyword arguments from untrusted user input applies as equally
> to these arguments as it does to `**extra`.

### `Aggregate()` 式

集計式 (aggregate expression) は [Func() 式](#func-expressions) の特殊なケースで、 `GROUP BY` 句が必要であることをクエリに通知します。 `Sum()` や `Count()` などの [集計関数](/ja/6.1/ref/models/querysets/#aggregation-functions) はすべて `Aggregate()` を継承しています。

`Aggregate` は式であり、ラップ式でもあるので、複雑な計算を表現できます：

```
from django.db.models import Count

Company.objects.annotate(
    managers_required=(Count("num_employees") / 4) + Count("num_managers")
)
```

`Aggregate` の API は以下の通りです：

#### `class Aggregate(*expressions, output_field=None, distinct=False, filter=None, default=None, order_by=None, **extra)`

#### `template`

この aggregate 用に生成される SQL を記述する、フォーマット文字列としてのクラス属性です。デフォルトは `'%(function)s(%(distinct)s%(expressions)s)'` です。

#### `function`

生成される集計関数を記述するクラス属性です。具体的には、 `function` が [`template`](#django.db.models.Aggregate.template) 内の `function` プレースホルダとして補間されます。デフォルトは `None` です。

#### `window_compatible`

ほとんどの集計関数は [`Window`](#django.db.models.expressions.Window) のソース式として使用できるので、デフォルトは `True` です。

#### `allow_distinct`

この集計関数が `distinct` キーワード引数を渡すことができるかどうかを決定するクラス属性。 `False` (デフォルト) に設定されている場合、 `distinct=True` が渡されると `TypeError` が発生します。

#### `allow_order_by`

> **New in Django 6.0**

A class attribute determining whether or not this aggregate function
allows passing a `order_by` keyword argument. If set to `False`
(default), `TypeError` is raised if `order_by` is passed as a value
other than `None`.

#### `empty_result_set_value`

ほとんどの集計関数は、空の結果セットに適用すると `NULL` となるため、デフォルトは `None` です。

位置引数 `expressions` には、式、モデルフィールドのトランスフォーム、またはモデルフィールドの名前を指定できます。これらは文字列に変換され、 `template` 内の `expressions` プレースホルダとして使用されます。

引数 `distinct` は、集計関数を `式` (または複数の `式` の場合は値の集合) ごとに呼び出すかどうかを決定します。この引数は [`allow_distinct`](#django.db.models.Aggregate.allow_distinct) が `True` に設定されている集計でのみサポートされます。

The `filter` argument takes a [Q object](/ja/6.1/ref/models/querysets/#q-objects) that's
used to filter the rows that are aggregated. See [条件付きの集計](/ja/6.1/ref/models/conditional-expressions/#conditional-aggregation)
and [アノテーションのフィルタリング](/ja/6.1/topics/db/aggregation/#filtering-on-annotations) for example usage.

The `order_by` argument behaves similarly to the `field_names` input of the
[`order_by()`](/ja/6.1/ref/models/querysets/#django.db.models.query.QuerySet.order_by) function, accepting a field name (with an optional
`"-"` prefix which indicates descending order) or an expression (or a tuple
or list of strings and/or expressions) that specifies the ordering of the
elements in the result.

引数 `default` は [`Coalesce`](/ja/6.1/ref/models/database-functions/#django.db.models.functions.Coalesce) に集計句と一緒に渡される値を取ります。これは、クエリセット(またはグループ化)にエントリがない場合に `None` 以外の値を返すように指定するのに便利です。

この `**extra` キーワード引数は `template` 属性に補間できる `key=value` のペアです。

> **Changed in Django 6.0**
>
> `order_by` 引数が追加されました。

### 独自の集計関数 (Aggregate Function) を作る

独自の集計関数を作成することもできます。最低限 `function` を定義する必要がありますが、生成される SQL を完全にカスタマイズすることもできます。以下に簡単な例を示します：

```
from django.db.models import Aggregate

class Sum(Aggregate):
    # Supports SUM(ALL field).
    function = "SUM"
    template = "%(function)s(%(all_values)s%(expressions)s)"
    allow_distinct = False
    arity = 1

    def __init__(self, expression, all_values=False, **extra):
        super().__init__(expression, all_values="ALL " if all_values else "", **extra)
```

### `Value()` 式

#### `class Value(value, output_field=None)`

`Value()` オブジェクトは式の最小の構成要素、つまり単純な値を表します。式の中で整数、真偽値、文字列の値を表す必要がある場合、その値を `Value()` で囲みます。

`Value()` を直接使用することはほとんどありません。 `F('field') + 1` という式を書くと、Djangoは暗黙のうちに `1` を `Value()` でラップし、単純な値をより複雑な式で使用できるようにします。式に文字列を渡したいときは `Value()` を使用する必要があります。ほとんどの式では、文字列引数をフィールド名として解釈します。例えば `Lower('name')` のように。

引数 `value` には、 `1`, `True`, `None` など、式に含める値を記述します。Django はこれらの Python の値を対応するデータベース型に変換する方法を知っています。

If no [output\_field](#output-field) is specified, it will be inferred from
the type of the provided `value` for many common types. For example, passing
an instance of [`datetime.datetime`](https://docs.python.org/3/library/datetime.html#datetime.datetime) as `value` defaults
`output_field` to [`DateTimeField`](/ja/6.1/ref/models/fields/#django.db.models.DateTimeField).

### `ExpressionWrapper()` 式

#### `class ExpressionWrapper(expression, output_field)`

`ExpressionWrapper` は他の式を囲み、 [output\_field](#output-field) のような他の式では利用できないプロパティへのアクセスを提供します。 `ExpressionWrapper` は [F() をアノテーションと一緒に使う](#using-f-with-annotations) で説明されているように、異なる型を持つ `F()` 式で算術演算を行う場合に必要です。

> **データベースでのキャストは行われません**
>
> `ExpressionWrapper` は ORM に対して出力フィールドを設定するだけで、データベースレベルでのキャストは行いません。データベースから特定の型を返すようにするには、代わりに [`Cast`](/ja/6.1/ref/models/database-functions/#django.db.models.functions.Cast) を使用してください。

### `JSONNull()` expression

> **New in Django 6.1**

#### `class JSONNull`

Specialized expression to represent JSON scalar `null` on a
[`JSONField`](/ja/6.1/ref/models/fields/#django.db.models.JSONField).

See [None の保存とクエリ](/ja/6.1/topics/db/queries/#storing-and-querying-for-none) for usage examples.

### 条件式

Conditional expressions allow you to use [`if`](https://docs.python.org/3/reference/compound_stmts.html#if) ... [`elif`](https://docs.python.org/3/reference/compound_stmts.html#elif) ...
[`else`](https://docs.python.org/3/reference/compound_stmts.html#else) logic in queries. Django natively supports SQL `CASE`
expressions. For more details see [条件式](/ja/6.1/ref/models/conditional-expressions/).

### `Subquery()` 式

#### `class Subquery(queryset, output_field=None)`

`Subquery` 式を使うと、 `QuerySet` に明示的にサブクエリを追加できます。

たとえば、各投稿にその投稿の最新コメントの投稿者のメールアドレスをアノテーションとして付けることができます：

```pycon
>>> from django.db.models import OuterRef, Subquery
>>> newest = Comment.objects.filter(post=OuterRef("pk")).order_by("-created_at")
>>> Post.objects.annotate(newest_commenter_email=Subquery(newest.values("email")[:1]))
```

PostgreSQLの場合、SQLは以下のようになります：

```sql
SELECT "post"."id", (
    SELECT U0."email"
    FROM "comment" U0
    WHERE U0."post_id" = ("post"."id")
    ORDER BY U0."created_at" DESC LIMIT 1
) AS "newest_commenter_email" FROM "post"
```

> **Note**
>
> この節の例は、Django にサブクエリを強制する方法を示すものです。場合によっては、同じタスクをより明確に、あるいは効率的に実行する等価なクエリセットを書けるかもしれません。

#### 外側のクエリセットからカラムを参照する

#### `class OuterRef(field)`

`OuterRef` は `Subquery` 内のクエリセットが外側のクエリまたはそのトランスフォームのフィールドから参照される必要がある場合に使用します。これは [`F`](#django.db.models.F) 式と同じように動作しますが、有効なフィールドを参照しているかどうかのチェックは外側のクエリセットが解決されるまで行われません。

`OuterRef` のインスタンスは、入れ子になった `Subquery` のインスタンスと一緒に使用できます。例えば、このクエリセットを正しく解決するには、 `Subquery` インスタンスの入れ子になったペア内にある必要があります：

```pycon
>>> Book.objects.filter(author=OuterRef(OuterRef("pk")))
```

#### サブクエリを単一のカラムに絞る

`Subquery` を `__in` ルックアップの対象として使う場合など、`Subquery` から単一のカラムを返さなければならないことがあります。たとえば、直近一日以内に公開された投稿のすべてのコメントを返す場合：

```pycon
>>> from datetime import timedelta
>>> from django.utils import timezone
>>> one_day_ago = timezone.now() - timedelta(days=1)
>>> posts = Post.objects.filter(published_at__gte=one_day_ago)
>>> Comment.objects.filter(post__in=Subquery(posts.values("pk")))
```

この場合、サブクエリは [`values()`](/ja/6.1/ref/models/querysets/#django.db.models.query.QuerySet.values) を使って単一のカラム、つまり投稿の主キーだけを返さなければなりません。

#### サブクエリを1行に絞る

サブクエリが複数行を返すのを防ぐには、クエリセットのスライス (`[:1]`) を使用します：

```pycon
>>> subquery = Subquery(newest.values("email")[:1])
>>> Post.objects.annotate(newest_commenter_email=subquery)
```

この場合、サブクエリは単一のカラムの単一の行、つまり最近作成されたコメントのメールアドレスだけを返す必要があります。

（スライスの代わりに [`get()`](/ja/6.1/ref/models/querysets/#django.db.models.query.QuerySet.get) を使うと、 `Subquery` 内でクエリセットが使われるまで `OuterRef` が解決できないため失敗します）

#### `Exists()` サブクエリ

#### `class Exists(queryset)`

`Exists` は SQL の `EXISTS` ステートメントを使う `サブクエリ` のサブクラスです。多くの場合、最初にマッチする行が見つかった時点でデータベースがサブクエリの評価を停止できるので、サブクエリよりも性能が良くなります。

たとえば、各投稿に直近1日以内のコメントがあるかどうかのアノテーションを付けることができます：

```pycon
>>> from django.db.models import Exists, OuterRef
>>> from datetime import timedelta
>>> from django.utils import timezone
>>> one_day_ago = timezone.now() - timedelta(days=1)
>>> recent_comments = Comment.objects.filter(
...     post=OuterRef("pk"),
...     created_at__gte=one_day_ago,
... )
>>> Post.objects.annotate(recent_comment=Exists(recent_comments))
```

PostgreSQLの場合、SQLは以下のようになります：

```sql
SELECT "post"."id", "post"."published_at", EXISTS(
    SELECT (1) as "a"
    FROM "comment" U0
    WHERE (
        U0."created_at" >= YYYY-MM-DD HH:MM:SS AND
        U0."post_id" = "post"."id"
    )
    LIMIT 1
) AS "recent_comment" FROM "post"
```

`Exists` に単一のカラムの参照を強制する必要はありません。列は破棄され、真偽値の結果が返されるからです。同様に、ソートは SQL の `EXISTS` サブクエリ内では重要ではなく、パフォーマンスを低下させるだけなので、自動的に破棄されます。

`~Exists()` を使って `NOT EXISTS` をクエリできます。

#### `Subquery()` または `Exists()` 式におけるフィルタリング

真偽値を返す `Subquery()` と `Exists()` は [`When`](/ja/6.1/ref/models/conditional-expressions/#django.db.models.expressions.When) 式で `condition` として使用したり、クエリセットに直接フィルタをかけたりすることができます：

```pycon
>>> recent_comments = Comment.objects.filter(...)  # From above
>>> Post.objects.filter(Exists(recent_comments))
```

これにより、サブクエリが `SELECT` カラムに追加されなくなり、パフォーマンスが向上する可能性があります。

#### `Subquery` 式の中で集計 (aggregate) を使う

集計 (aggregate) は `Subquery` の中で使用できますが、サブクエリのグループ化を正しく行うためには [`filter()`](/ja/6.1/ref/models/querysets/#django.db.models.query.QuerySet.filter), [`values()`](/ja/6.1/ref/models/querysets/#django.db.models.query.QuerySet.values), [`annotate()`](/ja/6.1/ref/models/querysets/#django.db.models.query.QuerySet.annotate) の特定の組み合わせを必要とします。

両方のモデルに `length` フィールドがあると仮定すると、投稿の長さがすべてのコメントの長さの合計よりも大きい投稿を見つけることができます：

```pycon
>>> from django.db.models import OuterRef, Subquery, Sum
>>> comments = Comment.objects.filter(post=OuterRef("pk")).order_by().values("post")
>>> total_comments = comments.annotate(total=Sum("length")).values("total")
>>> Post.objects.filter(length__gt=Subquery(total_comments))
```

最初の `filter(...)` はサブクエリを関連するパラメータに制限します。 `order_by()` は `Comment` モデルのデフォルトの [`ordering`](/ja/6.1/ref/models/options/#django.db.models.Options.ordering) (もしあれば) を削除します。 `value('post')` はコメントを `Post` で集計します。最後に、 `annotate(...)` が集計を行います。これらのクエリセットメソッドを適用する順番は重要です。この場合、サブクエリは1つのカラムに限定する必要があるため、 `values('total')` が必要となります。

これは `Subquery` 内で集計を行う唯一の方法です。 [`aggregate()`](/ja/6.1/ref/models/querysets/#django.db.models.query.QuerySet.aggregate) を使用すると、クエリセットを評価しようとします（そして `OuterRef` がある場合、これを解決することはできません）。

### 素の SQL 式

#### `class RawSQL(sql, params, output_field=None)`

データベース式では複雑な `WHERE` 句を簡単に表現できないことがあります。このような場合は `RawSQL` 式を使用してください。たとえば：

```pycon
>>> from django.db.models.expressions import RawSQL
>>> queryset.annotate(val=RawSQL("select col from sometable where othercol = %s", (param,)))
```

このような特別なルックアップは、（明示的にSQLコードを記述しているため）異なるデータベースエンジンに移植できない可能性があり、DRY原則に反するので、可能なら避けるべきです。

`RawSQL` 式は `__in` フィルタの対象としても使用できます：

```pycon
>>> queryset.filter(id__in=RawSQL("select id from sometable where col = %s", (param,)))
```

> **Warning**
>
> [SQLインジェクション攻撃](https://ja.wikipedia.org/wiki/SQL%E3%82%A4%E3%83%B3%E3%82%B8%E3%82%A7%E3%82%AF%E3%82%B7%E3%83%A7%E3%83%B3) を防ぐために、 `params` を使って、ユーザが操作できるパラメータをエスケープする必要があります。 `params` は必須引数で、ユーザが入力したデータでSQLを補間しないことを強制するためのものです。
>
> また、SQL文字列のプレースホルダを引用符で囲んではいけません。 この例では `%s` を引用符で囲んでいるため、SQLインジェクションの脆弱性があります：
>
> ```
> RawSQL("select col from sometable where othercol = '%s'")  # unsafe!
> ```
>
> Django が [SQL インジェクションを防ぐ](/ja/6.1/topics/security/#sql-injection-protection) 仕組みの説明があります。

### ウィンドウ関数

ウィンドウ関数は、パーティション上で関数を適用する方法を提供します。通常の集計関数が group by で定義された各セットに対して最終結果を計算するのに対し、ウィンドウ関数は [フレーム](#window-frames) とパーティション上で操作し、各行に対して結果を計算します。

同じクエリ内で複数のウィンドウを指定することができ、Django ORM では [QuerySet.annotate()](/ja/6.1/topics/db/aggregation/) 呼び出しに複数の式を含めることで実現します。ORMは名前付きウィンドウを使用しませんが、代わりに選択されたカラムの一部となります。

#### `class Window(expression, partition_by=None, order_by=None, frame=None, output_field=None)`

#### `template`

デフォルトは `%(expression)s OVER (%(window)s)` です。引数 `expression` だけを指定した場合、window 句は空白になります。

`Window` クラスは `OVER` 句のメインの式です。

引数の `expression` は [ウィンドウ関数](/ja/6.1/ref/models/database-functions/#window-functions), [集計関数](/ja/6.1/ref/models/querysets/#aggregation-functions), またはwindow句で互換性のある式です。

The `partition_by` argument accepts an expression or a sequence of
expressions (column names should be wrapped in an `F`-object) that control
the partitioning of the rows. Partitioning narrows which rows are used to
compute the result set.

[output\_field](#output-field) は引数か式で指定します。

`order_by` 引数には [`asc()`](#django.db.models.Expression.asc) と [`desc()`](#django.db.models.Expression.desc) を呼び出せる式、フィールド名の文字列 (オプションで降順を示す `"-"` をプレフィックスに付けられます)、または文字列や式のタプルやリストを渡すことができます。順序は式が適用される順番を制御します。例えば、パーティション内の行を合計した場合、最初の結果は最初の行の値になり、2番目は最初の行と2番目の行の合計になります。

The `frame` parameter specifies which other rows should be used in the
computation. See [フレーム](#window-frames) for details.

たとえば、各映画に同じスタジオによる同じジャンル・公開年の映画の平均レーティングでアノテーションを付ける場合：

```pycon
>>> from django.db.models import Avg, F, Window
>>> Movie.objects.annotate(
...     avg_rating=Window(
...         expression=Avg("rating"),
...         partition_by=[F("studio"), F("genre")],
...         order_by="released__year",
...     ),
... )
```

これにより、映画の評価が他の映画より高いか低いかをチェックできます。

同じウィンドウ、つまり同じパーティションとフレームに複数の式を適用したい場合があります。例えば、同じクエリで3つのウィンドウ関数を使用することで、各映画のグループ（同じスタジオ、ジャンル、リリース年）のベストとワーストの評価も含めるように、前の例を修正できます。前の例のパーティションとソートは、繰り返しを減らすために辞書に抽出されます：

```pycon
>>> from django.db.models import Avg, F, Max, Min, Window
>>> window = {
...     "partition_by": [F("studio"), F("genre")],
...     "order_by": "released__year",
... }
>>> Movie.objects.annotate(
...     avg_rating=Window(
...         expression=Avg("rating"),
...         **window,
...     ),
...     best=Window(
...         expression=Max("rating"),
...         **window,
...     ),
...     worst=Window(
...         expression=Min("rating"),
...         **window,
...     ),
... )
```

ウィンドウ関数に対するフィルタリングは、ルックアップが分離型でない（コネクタとして `OR` や `XOR` を使用していない）限り、集計を実行するクエリセットに対してもサポートされます。

たとえば、集計に依存し、ウィンドウ関数とフィールドに対して `OR` でフィルタされたクエリはサポートされていません。集計後に真偽値を返す関数を適用すると、通常はグループから除外されるはずの行が含まれる可能性があります：

```pycon
>>> qs = Movie.objects.annotate(
...     category_rank=Window(Rank(), partition_by="category", order_by="-rating"),
...     scenes_count=Count("actors"),
... ).filter(Q(category_rank__lte=3) | Q(title__contains="Batman"))
>>> list(qs)
NotImplementedError: Heterogeneous disjunctive predicates against window functions
are not implemented when performing conditional aggregation.
```

Django に組み込みのデータベースバックエンドでは、MySQL、 PostgreSQL、 Oracle がウィンドウ表現をサポートしています。ウィンドウ表現機能のサポートはデータベースによって異なります。例えば、 [`asc()`](#django.db.models.Expression.asc) や [`desc()`](#django.db.models.Expression.desc) のオプションはサポートされていないかもしれません。必要に応じてデータベースのドキュメントを参照してください。

#### フレーム

ウィンドウフレームでは、範囲ベースの行のシーケンスか、通常の行のシーケンスのいずれかを選択できます。

#### `class ValueRange(start=None, end=None, exclusion=None)`

#### `frame_type`

この属性は `'RANGE'` に設定されています。

PostgreSQLは `ValueRange` のサポートに制限があり、 `CURRENT ROW` や `UNBOUNDED FOLLOWING` のような標準的な開始点と終了点の使用しかサポートしていません。

#### `class RowRange(start=None, end=None, exclusion=None)`

#### `frame_type`

この属性は `'ROWS'` に設定されています。

どちらのクラスもテンプレートとともにSQLを返します：

```sql
%(frame_type)s BETWEEN %(start)s AND %(end)s
```

#### `class WindowFrameExclusion`

#### `CURRENT_ROW`

#### `GROUP`

#### `TIES`

#### `NO_OTHERS`

`exclusion` 引数は、サポートされているデータベースでウィンドウフレームから行（[`CURRENT_ROW`](#django.db.models.expressions.WindowFrameExclusion.CURRENT_ROW)）、グループ（[`GROUP`](#django.db.models.expressions.WindowFrameExclusion.GROUP)）、および同点（[`TIES`](#django.db.models.expressions.WindowFrameExclusion.TIES)）を除外するために使用できます。

```sql
%(frame_type)s BETWEEN %(start)s AND %(end)s EXCLUDE %(exclusion)s
```

フレームは、結果を計算するために使用される行を絞り込みます。ある開始点から指定された終了点までシフトします。フレームはパーティションの有無に関係なく使用できますが、決定論的な結果を得るためには、ウィンドウの順序を指定することを推奨します。フレームでは、フレーム内のピアは等価値を持つ行であり、ソート句がない場合はすべての行です。

フレームのデフォルトの開始点は `UNBOUNDED PRECEDING` で、パーティションの最初の行になります。終了点は ORM が生成する SQL に常に明示的に含まれ、デフォルトでは `UNBOUNDED FOLLOWING` です。デフォルトのフレームは、パーティションからセットの最後の行までの全ての行を含みます。

`start` および `end` 引数に受け入れられる値は、`None`、整数、またはゼロです。`start` に負の整数を指定するとN行前 `N PRECEDING` となり、`None` は先頭行 `UNBOUNDED PRECEDING` となります。`ROWS` モードでは、`start` に正の整数を指定するとN行後 `N FOLLOWING` となります。`end` には正の整数も受け入れられ、これによりN行後 `N FOLLOWING` となります。`ROWS` モードでは、`end` に負の整数を指定するとN行前 `N PRECEDING` となります。`start` と `end` の両方でゼロを指定すると現在の行 `CURRENT ROW` が返されます。

`CURRENT ROW` が含むものには違いがあります。 `ROWS` モードで指定された場合、フレームは現在の行から開始または終了します。 `RANGE` モードで指定された場合、フレームはソートの順序に従って最初か最後のピアから開始または終了します。 したがって、 `RANGE CURRENT ROW` は、ソートで指定された同じ値を持つ行に対して式を評価します。テンプレートは `start` と `end` の両方を含むので、これは次のように表現できます：

```
ValueRange(start=0, end=0)
```

映画の "ピア" が同じ年に同じジャンルで同じスタジオからリリースされた映画として記述されている場合、この `RowRange` の例では、映画の2つ前から2つ後のピアの平均評価で各映画にアノテーションを付けます：

```pycon
>>> from django.db.models import Avg, F, RowRange, Window
>>> Movie.objects.annotate(
...     avg_rating=Window(
...         expression=Avg("rating"),
...         partition_by=[F("studio"), F("genre")],
...         order_by="released__year",
...         frame=RowRange(start=-2, end=2),
...     ),
... )
```

データベースがサポートしていれば、パーティション内の式の値に基づいて開始点と終了点を指定することもできます。もし `Movie` モデルの `released` フィールドが各映画の公開月を保存している場合、この `ValueRange` の例では、各映画の12ヶ月前から12ヶ月後に公開された映画の同業者の平均レーティングでアノテーションを付けます：

```pycon
>>> from django.db.models import Avg, F, ValueRange, Window
>>> Movie.objects.annotate(
...     avg_rating=Window(
...         expression=Avg("rating"),
...         partition_by=[F("studio"), F("genre")],
...         order_by="released__year",
...         frame=ValueRange(start=-12, end=12),
...     ),
... )
```

## 技術的な情報

以下に、ライブラリの作者に役立つ技術的な実装の詳細を示します。以下の技術的な API と例は、 Django が提供する組み込み機能を拡張する汎用的なクエリ式を作成するのに役立ちます。

### 式 (Expression) API

クエリ式は [クエリ式 (expression) API](/ja/6.1/ref/models/lookups/#query-expression) を実装していますが、以下のようなメソッドや属性も公開しています。すべてのクエリ式は `Expression()` または関連するサブクラスを継承しなければなりません。

クエリ式が別の式をラップする場合、ラップされた式の適切なメソッドを呼び出す責任があります。

#### `class Expression`

#### `allowed_default`

この式が [`Field.db_default`](/ja/6.1/ref/models/fields/#django.db.models.Field.db_default) で使えることを Django に伝えます。デフォルトは `False` です。

#### `constraint_validation_compatible`

この式が制約の検証中に使用できることを Django に教えます。`constraint_validation_compatible` が `False` に設定された式は、ソース式を1つだけ持つ必要があります。デフォルトでは `True` です。

#### `contains_aggregate`

Django に、この式が集計を含んでいて、クエリに `GROUP BY` 句を追加する必要があることを伝えます。

#### `contains_over_clause`

この式が [`Window`](#django.db.models.expressions.Window) 式を含んでいることを Django に伝えます。これは例えば、データを変更するクエリでウィンドウ関数式を許可しないようにするのに使います。

#### `filterable`

この式が [`QuerySet.filter()`](/ja/6.1/ref/models/querysets/#django.db.models.query.QuerySet.filter) で参照できることを Django に伝えます。デフォルトは `True` です。

#### `window_compatible`

この式を [`Window`](#django.db.models.expressions.Window) のソース式として使えるかどうかを Django に伝えます。デフォルトは `False` です。

#### `empty_result_set_value`

Tells Django which value should be returned when the expression is used
to apply a function over an empty result set. Defaults to
[`NotImplemented`](https://docs.python.org/3/library/constants.html#NotImplemented) which forces the expression to be computed on
the database.

#### `set_returning`

この式が集合を返す関数を含むことを Django に知らせ、サブクエリの評価を強制します。これは例えば、アノテーションが自ら行を生成する場合に、一部の Postgres の集合を返す関数（例： `JSONB_PATH_QUERY` 、 `UNNEST` など）が最適化をスキップして正しく評価されるようにするために使用されます。デフォルトは `False` です。

#### `allows_composite_expressions`

この式が複合式を許容することを Django に知らせます。例えば、 [複合主キー](/ja/6.1/topics/composite-primary-key/#cpk-and-database-functions) をサポートするためなどに使用されます。デフォルトは `False` です。

#### `resolve_expression(query=None, allow_joins=True, reuse=None, summarize=False, for_save=False)`

クエリに追加する前に、式の前処理や検証を行う機会を提供します。 `resolve_expression()` は、ネストした式に対しても必ず呼び出されなければなりません。 `self` の `copy()` は、必要な変換を行ったものを返すべきです。

`query` はバックエンドクエリの実装です。

`allow_joins` はクエリで結合を使用するかどうかを指定する真偽値です。

`reuse` は複数結合シナリオのための再利用可能な結合のセットです。

`summarize` は真偽値で、`True` の場合、計算中のクエリが終端の集計クエリであることを示します。

`for_save` は真偽値で、 `True` の場合、実行中のクエリが作成または更新を行うことを示します。

#### `get_source_expressions()`

内部式の順序ありリストを返します。例えば：

```pycon
>>> Sum(F("foo")).get_source_expressions()
[F('foo')]
```

#### `set_source_expressions(expressions)`

式のリストを受け取り、それを `get_source_expressions()` が返せるように格納します。

#### `relabeled_clone(change_map)`

`self` のクローン（コピー）を返し、すべてのカラムエイリアスが再ラベル付けされます。カラムエイリアスは、サブクエリが作成される際に名前が変更されます。`relabeled_clone()` は、任意のネストされた式にも呼び出され、クローンに割り当てられるべきです。

`change_map` は古いエイリアスを新しいエイリアスにマッピングする辞書です。

実装例:

```
def relabeled_clone(self, change_map):
    clone = copy.copy(self)
    clone.expression = self.expression.relabeled_clone(change_map)
    return clone
```

#### `convert_value(value, expression, connection)`

式が `value` をより適切な型に強制するためのフック。

`expression` は `self` と同様です。

#### `get_group_by_cols()`

Responsible for returning the list of columns referenced by
this expression. `get_group_by_cols()` should be called on any
nested expressions. `F()` objects, in particular, hold a reference
to a column.

#### `asc(nulls_first=None, nulls_last=None)`

昇順でソートする準備が整った式を返します。

`nulls_first` と `nulls_last` は、null値がどのようにソートされるかを定義します。使用例については、[NULL 値のソートに F() を使う](#using-f-to-sort-null-values) を参照してください。

#### `desc(nulls_first=None, nulls_last=None)`

降順にソートする準備が整った式を返します。

`nulls_first` と `nulls_last` は、null値がどのようにソートされるかを定義します。使用例については、[NULL 値のソートに F() を使う](#using-f-to-sort-null-values) を参照してください。

#### `reverse_ordering()`

Returns `self` with any modifications required to reverse the sort
order within an `order_by` call. As an example, an expression
implementing `NULLS LAST` would change its value to be
`NULLS FIRST`. Modifications are only required for expressions that
implement sort order like `OrderBy`. This method is called when
[`reverse()`](/ja/6.1/ref/models/querysets/#django.db.models.query.QuerySet.reverse) is called on a
queryset.

### 独自のクエリ式を書く

他のクエリ式を使用したり、他のクエリ式と統合したりする独自のクエリ式クラスを書くことができます。組み込みの [Func() 式](#func-expressions) を使用せずに `COALESCE` SQL関数の実装を書く例を見てみましょう。

SQL 関数 `COALESCE` はカラムや値のリストを受け取るように定義されています。この関数は `NULL` でない最初のカラムまたは値を返します。

まずはSQL生成に使用するテンプレートと、いくつかの属性を設定する `__init__()` メソッドを定義します：

```
from django.db.models import Expression

class Coalesce(Expression):
    template = "COALESCE( %(expressions)s )"

    def __init__(self, expressions, output_field):
        super().__init__(output_field=output_field)
        if len(expressions) < 2:
            raise ValueError("expressions must have at least 2 elements")
        for expression in expressions:
            if not hasattr(expression, "resolve_expression"):
                raise TypeError("%r is not an Expression" % expression)
        self.expressions = expressions
```

少なくとも 2 つのカラムまたは値を必要とし、式であることを確認するなど、パラメータの基本的な検証を行います。ここで [output\_field](#output-field) を要求しているのは、 Django が最終的な結果をどのようなモデルフィールドに代入すべきかを知るためです。

前処理とバリデーションを実装します。この時点では独自のバリデーションを行っていないので、ネストした式に委譲します：

```
def resolve_expression(
    self, query=None, allow_joins=True, reuse=None, summarize=False, for_save=False
):
    c = self.copy()
    c.is_summary = summarize
    for pos, expression in enumerate(self.expressions):
        c.expressions[pos] = expression.resolve_expression(
            query, allow_joins, reuse, summarize, for_save
        )
    return c
```

次に、SQLを生成するメソッドを書きます：

```
def as_sql(self, compiler, connection, template=None):
    sql_expressions, sql_params = [], []
    for expression in self.expressions:
        sql, params = compiler.compile(expression)
        sql_expressions.append(sql)
        sql_params.extend(params)
    template = template or self.template
    data = {"expressions": ",".join(sql_expressions)}
    return template % data, tuple(sql_params)

def as_oracle(self, compiler, connection):
    """
    Example of vendor specific handling (Oracle in this case).
    Let's make the function name lowercase.
    """
    return self.as_sql(compiler, connection, template="coalesce( %(expressions)s )")
```

`as_sql()` メソッドはカスタムキーワード引数をサポート可能で、これにより `as_vendorname()` メソッドがSQL文字列を生成するためのデータをオーバーライドできます。`as_vendorname()` メソッド内で `self` を変更するよりも、`as_sql()` キーワード引数を使用してカスタマイズする方が好ましいです。前者は異なるデータベースバックエンドで実行する際にエラーを引き起こす可能性があるためです。クラスがクラス属性に依存してデータを定義している場合は、`as_sql()` メソッドでオーバーライドを許可することを検討してください。

`compiler.compile()` メソッドを使って各 `expressions` のSQLを生成し、その結果をカンマで連結します。そして、テンプレートにデータを入力し、SQLとパラメータを返します。

また、Oracle バックエンドに特化したカスタム実装も定義しました。Oracle バックエンドが使用されている場合は、 `as_sql()` の代わりに `as_oracle()` 関数が呼び出されます。

最後に、クエリ式が他のクエリ式と協調できるようにするためのメソッドを実装します：

```
def get_source_expressions(self):
    return self.expressions

def set_source_expressions(self, expressions):
    self.expressions = expressions
```

どう動作するか見てみましょう：

```pycon
>>> from django.db.models import F, Value, CharField
>>> qs = Company.objects.annotate(
...     tagline=Coalesce(
...         [F("motto"), F("ticker_name"), F("description"), Value("No Tagline")],
...         output_field=CharField(),
...     )
... )
>>> for c in qs:
...     print("%s: %s" % (c.name, c.tagline))
...
Google: Do No Evil
Apple: AAPL
Yahoo: Internet Company
Django Software Foundation: No Tagline
```

#### SQL インジェクションを防ぐ

`Func` の `__init__()` (`**extra`) および `as_sql()` (`**extra_context`) のキーワード引数は、 (データベースドライバがエスケープするような) クエリパラメータとして渡されるのではなく、SQL 文字列に補間されるので、信頼できないユーザ入力を含んではいけません。

例えば、`substring` がユーザーが入力したものである場合、この関数は SQL インジェクションに対して脆弱です：

```
from django.db.models import Func

class Position(Func):
    function = "POSITION"
    template = "%(function)s('%(substring)s' in %(expressions)s)"

    def __init__(self, expression, substring):
        # substring=substring is an SQL injection vulnerability!
        super().__init__(expression, substring=substring)
```

この関数はパラメータなしで SQL 文字列を生成します。 `substring` はキーワード引数として `super().__init__()` に渡されるので、クエリがデータベースに送信される前に SQL 文字列に補間されます。

以下が修正後の実装です：

```
class Position(Func):
    function = "POSITION"
    arg_joiner = " IN "

    def __init__(self, expression, substring):
        super().__init__(substring, expression)
```

代わりに `substring` を位置引数として渡すと、データベースクエリのパラメータとして渡されます。

### サードパーティのデータベースバックエンドへのサポートを追加する

ある関数で異なる SQL 構文を使用するデータベースバックエンドを使用している場合は、 その関数のクラスに新しいメソッドを追加することで対応できます。

例えば Microsoft SQL Server 用のバックエンドを書くとしましょう。このバックエンドでは [`Length`](/ja/6.1/ref/models/database-functions/#django.db.models.functions.Length) 関数に `LENGTH` の代わりに `LEN` という SQL を使用します。 `as_sqlserver()` という新しいメソッドを `Length` クラスに追加します：

```
from django.db.models.functions import Length

def sqlserver_length(self, compiler, connection):
    return self.as_sql(compiler, connection, function="LEN")

Length.as_sqlserver = sqlserver_length
```

`as_sql()` の `template` パラメータを使って SQL をカスタマイズすることもできます。

`django.db.connection.vendor` がバックエンドに `sqlserver` を返すので、 `as_sqlserver()` を使用します。

サードパーティのバックエンドは、バックエンドパッケージのトップレベルの `__init__.py` ファイル、またはトップレベルの `__init__.py` からインポートされたトップレベルの `expressions.py` ファイル (またはパッケージ) に関数を登録できます。

使用しているバックエンドにパッチを当てたいユーザプロジェクトでは、このコードを [`AppConfig.ready()`](/ja/6.1/ref/applications/#django.apps.AppConfig.ready) メソッドに記述します。
