{"title":"複合主キー","version":"6.0","locale":"ja","docname":"topics/composite-primary-key","url":"/ja/6.0/topics/composite-primary-key/","canonical":"https://djangodocs.dev/ja/6.0/topics/composite-primary-key/","summary":"New in Django 5.2 Django では、すべてのモデルに主キーが存在します。デフォルトでは、この主キーは単一のフィールドで構成されます。 ほとんどの場合、単一の主キーで十分です。しかし、データベース設計においては、複数のフィールドからなる主キーが必要になることもあります。…","html":"<h1>複合主キー<a class=\"heading-anchor\" href=\"#composite-primary-keys\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h1>\n<aside class=\"version-note version-added\" data-version=\"5.2\">\n<p class=\"version-note-title\">New in Django 5.2</p></aside>\n<p>Django では、すべてのモデルに主キーが存在します。デフォルトでは、この主キーは単一のフィールドで構成されます。</p>\n<p>ほとんどの場合、単一の主キーで十分です。しかし、データベース設計においては、複数のフィールドからなる主キーが必要になることもあります。</p>\n<p>複合主キーを使用するには、モデルを定義する際に <code class=\"docutils literal notranslate\"><span class=\"pre\">pk</span></code> 属性を <a class=\"reference internal\" href=\"/ja/6.0/ref/models/fields/#django.db.models.CompositePrimaryKey\" title=\"django.db.models.CompositePrimaryKey\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">CompositePrimaryKey</span></code></a> に設定します：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">Product</span><span class=\"p\">(</span><span class=\"n\">models</span><span class=\"o\">.</span><span class=\"n\">Model</span><span class=\"p\">):</span>\n    <span class=\"n\">name</span> <span class=\"o\">=</span> <span class=\"n\">models</span><span class=\"o\">.</span><span class=\"n\">CharField</span><span class=\"p\">(</span><span class=\"n\">max_length</span><span class=\"o\">=</span><span class=\"mi\">100</span><span class=\"p\">)</span>\n\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">Order</span><span class=\"p\">(</span><span class=\"n\">models</span><span class=\"o\">.</span><span class=\"n\">Model</span><span class=\"p\">):</span>\n    <span class=\"n\">reference</span> <span class=\"o\">=</span> <span class=\"n\">models</span><span class=\"o\">.</span><span class=\"n\">CharField</span><span class=\"p\">(</span><span class=\"n\">max_length</span><span class=\"o\">=</span><span class=\"mi\">20</span><span class=\"p\">,</span> <span class=\"n\">primary_key</span><span class=\"o\">=</span><span class=\"kc\">True</span><span class=\"p\">)</span>\n\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">OrderLineItem</span><span class=\"p\">(</span><span class=\"n\">models</span><span class=\"o\">.</span><span class=\"n\">Model</span><span class=\"p\">):</span>\n    <span class=\"n\">pk</span> <span class=\"o\">=</span> <span class=\"n\">models</span><span class=\"o\">.</span><span class=\"n\">CompositePrimaryKey</span><span class=\"p\">(</span><span class=\"s2\">&quot;product_id&quot;</span><span class=\"p\">,</span> <span class=\"s2\">&quot;order_id&quot;</span><span class=\"p\">)</span>\n    <span class=\"n\">product</span> <span class=\"o\">=</span> <span class=\"n\">models</span><span class=\"o\">.</span><span class=\"n\">ForeignKey</span><span class=\"p\">(</span><span class=\"n\">Product</span><span class=\"p\">,</span> <span class=\"n\">on_delete</span><span class=\"o\">=</span><span class=\"n\">models</span><span class=\"o\">.</span><span class=\"n\">CASCADE</span><span class=\"p\">)</span>\n    <span class=\"n\">order</span> <span class=\"o\">=</span> <span class=\"n\">models</span><span class=\"o\">.</span><span class=\"n\">ForeignKey</span><span class=\"p\">(</span><span class=\"n\">Order</span><span class=\"p\">,</span> <span class=\"n\">on_delete</span><span class=\"o\">=</span><span class=\"n\">models</span><span class=\"o\">.</span><span class=\"n\">CASCADE</span><span class=\"p\">)</span>\n    <span class=\"n\">quantity</span> <span class=\"o\">=</span> <span class=\"n\">models</span><span class=\"o\">.</span><span class=\"n\">IntegerField</span><span class=\"p\">()</span>\n</code></pre></div>\n<p>これにより、Django はテーブル作成時に複合主キー（ <code class=\"docutils literal notranslate\"><span class=\"pre\">PRIMARY</span> <span class=\"pre\">KEY</span> <span class=\"pre\">(product_id,</span> <span class=\"pre\">order_id)</span></code> ）を作成するようになります。</p>\n<p>複合主キーは <code class=\"docutils literal notranslate\"><span class=\"pre\">tuple</span></code> （タプル）で表現されます：</p>\n<div class=\"code-block\" data-language=\"pycon\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python console</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python console code\"><code><span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">product</span> <span class=\"o\">=</span> <span class=\"n\">Product</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">create</span><span class=\"p\">(</span><span class=\"n\">name</span><span class=\"o\">=</span><span class=\"s2\">&quot;apple&quot;</span><span class=\"p\">)</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">order</span> <span class=\"o\">=</span> <span class=\"n\">Order</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">create</span><span class=\"p\">(</span><span class=\"n\">reference</span><span class=\"o\">=</span><span class=\"s2\">&quot;A755H&quot;</span><span class=\"p\">)</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">item</span> <span class=\"o\">=</span> <span class=\"n\">OrderLineItem</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">create</span><span class=\"p\">(</span><span class=\"n\">product</span><span class=\"o\">=</span><span class=\"n\">product</span><span class=\"p\">,</span> <span class=\"n\">order</span><span class=\"o\">=</span><span class=\"n\">order</span><span class=\"p\">,</span> <span class=\"n\">quantity</span><span class=\"o\">=</span><span class=\"mi\">1</span><span class=\"p\">)</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">item</span><span class=\"o\">.</span><span class=\"n\">pk</span>\n<span class=\"go\">(1, &quot;A755H&quot;)</span>\n</code></pre></div>\n<p><a class=\"reference internal\" href=\"/ja/6.0/ref/models/instances/#django.db.models.Model.pk\" title=\"django.db.models.Model.pk\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">pk</span></code></a> 属性に <code class=\"docutils literal notranslate\"><span class=\"pre\">tuple</span></code> を代入することで、対応するフィールドの値をまとめて設定できます：</p>\n<div class=\"code-block\" data-language=\"pycon\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python console</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python console code\"><code><span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">item</span> <span class=\"o\">=</span> <span class=\"n\">OrderLineItem</span><span class=\"p\">(</span><span class=\"n\">pk</span><span class=\"o\">=</span><span class=\"p\">(</span><span class=\"mi\">2</span><span class=\"p\">,</span> <span class=\"s2\">&quot;B142C&quot;</span><span class=\"p\">))</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">item</span><span class=\"o\">.</span><span class=\"n\">pk</span>\n<span class=\"go\">(2, &quot;B142C&quot;)</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">item</span><span class=\"o\">.</span><span class=\"n\">product_id</span>\n<span class=\"go\">2</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">item</span><span class=\"o\">.</span><span class=\"n\">order_id</span>\n<span class=\"go\">&quot;B142C&quot;</span>\n</code></pre></div>\n<p>複合主キーは、 <code class=\"docutils literal notranslate\"><span class=\"pre\">tuple</span></code> を使ってフィルタリングできます：</p>\n<div class=\"code-block\" data-language=\"pycon\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python console</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python console code\"><code><span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">OrderLineItem</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">filter</span><span class=\"p\">(</span><span class=\"n\">pk</span><span class=\"o\">=</span><span class=\"p\">(</span><span class=\"mi\">1</span><span class=\"p\">,</span> <span class=\"s2\">&quot;A755H&quot;</span><span class=\"p\">))</span><span class=\"o\">.</span><span class=\"n\">count</span><span class=\"p\">()</span>\n<span class=\"go\">1</span>\n</code></pre></div>\n<p><a class=\"reference internal\" href=\"#cpk-and-relations\"><span class=\"std std-ref\">リレーションシップフィールド</span></a> (<a class=\"reference internal\" href=\"/ja/6.0/ref/contrib/contenttypes/#django.contrib.contenttypes.fields.GenericForeignKey\" title=\"django.contrib.contenttypes.fields.GenericForeignKey\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">GenericForeignKey</span></code></a> を含む) や Django 管理サイトにおける複合主キーのサポートは、現在も開発中です。現時点では、複合主キーを持つモデルは Django の管理サイトに登録できません。将来のリリースで対応が追加される予定です。</p>\n<section id=\"migrating-to-a-composite-primary-key\">\n<h2>複合主キーへの移行<a class=\"heading-anchor\" href=\"#migrating-to-a-composite-primary-key\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>Django は、テーブル作成後に複合主キーへマイグレーションしたり、それを元に戻したりする操作をサポートしていません。また、複合主キーにフィールドを追加・削除することもサポートされていません。</p>\n<p>既存のテーブルを単一の主キーから複合主キーに移行したい場合は、利用中のデータベースバックエンドの手順にしたがって操作してください。</p>\n<p>複合主キーを設定できたら、モデルに <code class=\"docutils literal notranslate\"><span class=\"pre\">CompositePrimaryKey</span></code> フィールドを追加してください。これにより、Django はその複合主キーを正しく認識し、適切に扱えるようになります。</p>\n<p>主キーフィールドに対するマイグレーション操作（たとえば <code class=\"docutils literal notranslate\"><span class=\"pre\">AddField</span></code> や <code class=\"docutils literal notranslate\"><span class=\"pre\">AlterField</span></code> ）はサポートされていませんが、 <code class=\"docutils literal notranslate\"><span class=\"pre\">makemigrations</span></code> は変更を検出します。</p>\n<p>エラーを避けるために、上記のようなマイグレーションは <code class=\"docutils literal notranslate\"><span class=\"pre\">--fake</span></code> オプションを付けて適用することを推奨します。</p>\n<p>代わりに、 <a class=\"reference internal\" href=\"/ja/6.0/ref/migration-operations/#django.db.migrations.operations.SeparateDatabaseAndState\" title=\"django.db.migrations.operations.SeparateDatabaseAndState\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">SeparateDatabaseAndState</span></code></a> を使うことで、データベース固有のマイグレーションと Django による状態管理用マイグレーションを、1つの操作としてまとめて実行することもできます。</p>\n</section>\n<section id=\"composite-primary-keys-and-relations\">\n<span id=\"cpk-and-relations\"></span><h2>複合主キーとリレーション<a class=\"heading-anchor\" href=\"#composite-primary-keys-and-relations\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p><a class=\"reference internal\" href=\"/ja/6.0/ref/models/fields/#relationship-fields\"><span class=\"std std-ref\">リレーションシップフィールド</span></a> (<a class=\"reference internal\" href=\"/ja/6.0/ref/contrib/contenttypes/#generic-relations\"><span class=\"std std-ref\">ジェネリックリレーション</span></a> を含む) は、複合主キーをサポートしていません。</p>\n<p>たとえば先ほどの <code class=\"docutils literal notranslate\"><span class=\"pre\">OrderLineItem</span></code> モデルにおいて、次のような使い方はサポートされていません：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">Foo</span><span class=\"p\">(</span><span class=\"n\">models</span><span class=\"o\">.</span><span class=\"n\">Model</span><span class=\"p\">):</span>\n    <span class=\"n\">item</span> <span class=\"o\">=</span> <span class=\"n\">models</span><span class=\"o\">.</span><span class=\"n\">ForeignKey</span><span class=\"p\">(</span><span class=\"n\">OrderLineItem</span><span class=\"p\">,</span> <span class=\"n\">on_delete</span><span class=\"o\">=</span><span class=\"n\">models</span><span class=\"o\">.</span><span class=\"n\">CASCADE</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>これは、現在 <code class=\"docutils literal notranslate\"><span class=\"pre\">ForeignKey</span></code> が複合主キーを持つモデルを参照できないためです。</p>\n<p>この制限を回避するには、代わりに <code class=\"docutils literal notranslate\"><span class=\"pre\">ForeignObject</span></code> が使えます：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">Foo</span><span class=\"p\">(</span><span class=\"n\">models</span><span class=\"o\">.</span><span class=\"n\">Model</span><span class=\"p\">):</span>\n    <span class=\"n\">item_order_id</span> <span class=\"o\">=</span> <span class=\"n\">models</span><span class=\"o\">.</span><span class=\"n\">CharField</span><span class=\"p\">(</span><span class=\"n\">max_length</span><span class=\"o\">=</span><span class=\"mi\">20</span><span class=\"p\">)</span>\n    <span class=\"n\">item_product_id</span> <span class=\"o\">=</span> <span class=\"n\">models</span><span class=\"o\">.</span><span class=\"n\">IntegerField</span><span class=\"p\">()</span>\n    <span class=\"n\">item</span> <span class=\"o\">=</span> <span class=\"n\">models</span><span class=\"o\">.</span><span class=\"n\">ForeignObject</span><span class=\"p\">(</span>\n        <span class=\"n\">OrderLineItem</span><span class=\"p\">,</span>\n        <span class=\"n\">on_delete</span><span class=\"o\">=</span><span class=\"n\">models</span><span class=\"o\">.</span><span class=\"n\">CASCADE</span><span class=\"p\">,</span>\n        <span class=\"n\">from_fields</span><span class=\"o\">=</span><span class=\"p\">(</span><span class=\"s2\">&quot;item_order_id&quot;</span><span class=\"p\">,</span> <span class=\"s2\">&quot;item_product_id&quot;</span><span class=\"p\">),</span>\n        <span class=\"n\">to_fields</span><span class=\"o\">=</span><span class=\"p\">(</span><span class=\"s2\">&quot;order_id&quot;</span><span class=\"p\">,</span> <span class=\"s2\">&quot;product_id&quot;</span><span class=\"p\">),</span>\n    <span class=\"p\">)</span>\n</code></pre></div>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">ForeignObject</span></code> は <code class=\"docutils literal notranslate\"><span class=\"pre\">ForeignKey</span></code> によく似ていますが、データベース上にカラム (例: <code class=\"docutils literal notranslate\"><span class=\"pre\">item_id</span></code>)、外部キー制約、インデックスなどを作成しない点、 <code class=\"docutils literal notranslate\"><span class=\"pre\">on_delete</span></code> 引数が無視される点が異なります。</p>\n</section>\n<section id=\"composite-primary-keys-and-database-functions\">\n<span id=\"cpk-and-database-functions\"></span><h2>複合主キーとデータベース関数<a class=\"heading-anchor\" href=\"#composite-primary-keys-and-database-functions\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>多くのデータベース関数は、単一の式しか受け付けません。</p>\n<div class=\"code-block\" data-language=\"sql\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">SQL</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"SQL code\"><code><span class=\"k\">MAX</span><span class=\"p\">(</span><span class=\"ss\">&quot;order_id&quot;</span><span class=\"p\">)</span><span class=\"w\">  </span><span class=\"c1\">-- OK</span>\n<span class=\"k\">MAX</span><span class=\"p\">(</span><span class=\"ss\">&quot;product_id&quot;</span><span class=\"p\">,</span><span class=\"w\"> </span><span class=\"ss\">&quot;order_id&quot;</span><span class=\"p\">)</span><span class=\"w\">  </span><span class=\"c1\">-- ERROR</span>\n</code></pre></div>\n<p>複合主キーは複数のカラム表現を含むため、このような関数に渡すと、 <code class=\"docutils literal notranslate\"><span class=\"pre\">ValueError</span></code> が発生します。 ただし <code class=\"docutils literal notranslate\"><span class=\"pre\">Count</span></code> だけは例外で、複合主キーでも利用できます。</p>\n<div class=\"code-block\" data-language=\"python\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python code\"><code><span class=\"n\">Max</span><span class=\"p\">(</span><span class=\"s2\">&quot;order_id&quot;</span><span class=\"p\">)</span>  <span class=\"c1\"># OK</span>\n<span class=\"n\">Max</span><span class=\"p\">(</span><span class=\"s2\">&quot;pk&quot;</span><span class=\"p\">)</span>  <span class=\"c1\"># ValueError</span>\n<span class=\"n\">Count</span><span class=\"p\">(</span><span class=\"s2\">&quot;pk&quot;</span><span class=\"p\">)</span>  <span class=\"c1\"># OK</span>\n</code></pre></div>\n</section>\n<section id=\"composite-primary-keys-in-forms\">\n<h2>フォーム内での複合主キー<a class=\"heading-anchor\" href=\"#composite-primary-keys-in-forms\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>複合主キーは仮想フィールドであり、単一のデータベースカラムを表さないため、ModelForm には含まれません。</p>\n<p>たとえば、次のようなフォームを考えてみましょう：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">OrderLineItemForm</span><span class=\"p\">(</span><span class=\"n\">forms</span><span class=\"o\">.</span><span class=\"n\">ModelForm</span><span class=\"p\">):</span>\n    <span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">Meta</span><span class=\"p\">:</span>\n        <span class=\"n\">model</span> <span class=\"o\">=</span> <span class=\"n\">OrderLineItem</span>\n        <span class=\"n\">fields</span> <span class=\"o\">=</span> <span class=\"s2\">&quot;__all__&quot;</span>\n</code></pre></div>\n<p>このフォームには、複合主キーのための <code class=\"docutils literal notranslate\"><span class=\"pre\">pk</span></code> フィールドは含まれません：</p>\n<div class=\"code-block\" data-language=\"pycon\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python console</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python console code\"><code><span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">OrderLineItemForm</span><span class=\"p\">()</span>\n<span class=\"go\">&lt;OrderLineItemForm bound=False, valid=Unknown, fields=(product;order;quantity)&gt;</span>\n</code></pre></div>\n<p>複合主キーである <code class=\"docutils literal notranslate\"><span class=\"pre\">pk</span></code> をフォームフィールドとして指定しようとすると、存在しないフィールドとして <a class=\"reference internal\" href=\"/ja/6.0/ref/exceptions/#django.core.exceptions.FieldError\" title=\"django.core.exceptions.FieldError\"><code class=\"xref py py-exc docutils literal notranslate\"><span class=\"pre\">FieldError</span></code></a> が発生します。</p>\n<aside class=\"admonition-primary-key-fields-are-read-only admonition\">\n<p class=\"admonition-title\">主キーフィールドは読み取り専用です</p>\n<p>既存のオブジェクトで主キーの値を変更してから保存すると、新しいオブジェクトが元のオブジェクトとは別に作成されます (<a class=\"reference internal\" href=\"/ja/6.0/ref/models/fields/#django.db.models.Field.primary_key\" title=\"django.db.models.Field.primary_key\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">Field.primary_key</span></code></a> を参照)。</p>\n<p>これは複合主キーの場合も同様です。そのため、すべての主キーフィールドに対して <a class=\"reference internal\" href=\"/ja/6.0/ref/models/fields/#django.db.models.Field.editable\" title=\"django.db.models.Field.editable\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">Field.editable</span></code></a> を <code class=\"docutils literal notranslate\"><span class=\"pre\">False</span></code> に設定し、ModelForm から除外することを検討してください。</p>\n</aside>\n</section>\n<section id=\"composite-primary-keys-in-model-validation\">\n<h2>モデルバリデーションと複合主キー<a class=\"heading-anchor\" href=\"#composite-primary-keys-in-model-validation\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">pk</span></code> は仮想フィールドなので、 <a class=\"reference internal\" href=\"/ja/6.0/ref/models/instances/#django.db.models.Model.clean_fields\" title=\"django.db.models.Model.clean_fields\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">Model.clean_fields()</span></code></a> の <code class=\"docutils literal notranslate\"><span class=\"pre\">exclude</span></code> 引数に <code class=\"docutils literal notranslate\"><span class=\"pre\">pk</span></code> を指定しても効果はありません。複合主キーの各フィールドをバリデーションから除外したい場合は、それぞれのフィールド名を個別に指定してください。一方、 <a class=\"reference internal\" href=\"/ja/6.0/ref/models/instances/#django.db.models.Model.validate_unique\" title=\"django.db.models.Model.validate_unique\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">Model.validate_unique()</span></code></a> に対しては <code class=\"docutils literal notranslate\"><span class=\"pre\">exclude={&quot;pk&quot;}</span></code> を指定することで、一意性のチェックをスキップできます。</p>\n</section>\n<section id=\"building-composite-primary-key-ready-applications\">\n<h2>複合主キーに対応したアプリケーションをつくる<a class=\"heading-anchor\" href=\"#building-composite-primary-key-ready-applications\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>複合主キーが導入される前は、モデルの主キーとなる単一フィールドを見つけたいとき、各フィールドの <a class=\"reference internal\" href=\"/ja/6.0/ref/models/fields/#django.db.models.Field.primary_key\" title=\"django.db.models.Field.primary_key\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">primary_key</span></code></a> 属性を確認するだけで済みました：</p>\n<div class=\"code-block\" data-language=\"pycon\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python console</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python console code\"><code><span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">pk_field</span> <span class=\"o\">=</span> <span class=\"kc\">None</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"k\">for</span> <span class=\"n\">field</span> <span class=\"ow\">in</span> <span class=\"n\">Product</span><span class=\"o\">.</span><span class=\"n\">_meta</span><span class=\"o\">.</span><span class=\"n\">get_fields</span><span class=\"p\">():</span>\n<span class=\"gp\">... </span>    <span class=\"k\">if</span> <span class=\"n\">field</span><span class=\"o\">.</span><span class=\"n\">primary_key</span><span class=\"p\">:</span>\n<span class=\"gp\">... </span>        <span class=\"n\">pk_field</span> <span class=\"o\">=</span> <span class=\"n\">field</span>\n<span class=\"gp\">... </span>        <span class=\"k\">break</span>\n<span class=\"gp\">...</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">pk_field</span>\n<span class=\"go\">&lt;django.db.models.fields.AutoField: id&gt;</span>\n</code></pre></div>\n<p>しかし <a class=\"reference internal\" href=\"/ja/6.0/ref/models/fields/#django.db.models.Field.primary_key\" title=\"django.db.models.Field.primary_key\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">primary</span> <span class=\"pre\">key</span></code></a> 属性はひとつのモデルにつき最大ひとつのフィールドしか <code class=\"docutils literal notranslate\"><span class=\"pre\">True</span></code> を取れないという制約があるため、複合主キーのもとではすべて <code class=\"docutils literal notranslate\"><span class=\"pre\">False</span></code> になってしまい、これでは主キーを構成するフィールドを特定するためには使えません。</p>\n<div class=\"code-block\" data-language=\"pycon\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python console</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python console code\"><code><span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">pk_fields</span> <span class=\"o\">=</span> <span class=\"p\">[]</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"k\">for</span> <span class=\"n\">field</span> <span class=\"ow\">in</span> <span class=\"n\">OrderLineItem</span><span class=\"o\">.</span><span class=\"n\">_meta</span><span class=\"o\">.</span><span class=\"n\">get_fields</span><span class=\"p\">():</span>\n<span class=\"gp\">... </span>    <span class=\"k\">if</span> <span class=\"n\">field</span><span class=\"o\">.</span><span class=\"n\">primary_key</span><span class=\"p\">:</span>\n<span class=\"gp\">... </span>        <span class=\"n\">pk_fields</span><span class=\"o\">.</span><span class=\"n\">append</span><span class=\"p\">(</span><span class=\"n\">field</span><span class=\"p\">)</span>\n<span class=\"gp\">...</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">pk_fields</span>\n<span class=\"go\">[]</span>\n</code></pre></div>\n<p>複合主キーに正しく対応するコードを書くためには、代わりに <a class=\"reference internal\" href=\"/ja/6.0/ref/models/meta/#django.db.models.options.Options.pk_fields\" title=\"django.db.models.options.Options.pk_fields\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">_meta.pk_fields</span></code></a> 属性を使用してください：</p>\n<div class=\"code-block\" data-language=\"pycon\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python console</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python console code\"><code><span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">Product</span><span class=\"o\">.</span><span class=\"n\">_meta</span><span class=\"o\">.</span><span class=\"n\">pk_fields</span>\n<span class=\"go\">[&lt;django.db.models.fields.AutoField: id&gt;]</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">OrderLineItem</span><span class=\"o\">.</span><span class=\"n\">_meta</span><span class=\"o\">.</span><span class=\"n\">pk_fields</span>\n<span class=\"go\">[</span>\n<span class=\"go\">    &lt;django.db.models.fields.ForeignKey: product&gt;,</span>\n<span class=\"go\">    &lt;django.db.models.fields.ForeignKey: order&gt;</span>\n<span class=\"go\">]</span>\n</code></pre></div>\n</section>","rootId":"composite-primary-keys","toc":[{"title":"複合主キーへの移行","anchor":"migrating-to-a-composite-primary-key","children":[]},{"title":"複合主キーとリレーション","anchor":"composite-primary-keys-and-relations","children":[]},{"title":"複合主キーとデータベース関数","anchor":"composite-primary-keys-and-database-functions","children":[]},{"title":"フォーム内での複合主キー","anchor":"composite-primary-keys-in-forms","children":[]},{"title":"モデルバリデーションと複合主キー","anchor":"composite-primary-keys-in-model-validation","children":[]},{"title":"複合主キーに対応したアプリケーションをつくる","anchor":"building-composite-primary-key-ready-applications","children":[]}],"breadcrumbs":[{"docname":"topics/index","title":"Django を使う","url":"/ja/6.0/topics/"}],"prev":{"docname":"topics/conditional-view-processing","title":"条件付きのビュー処理","url":"/ja/6.0/topics/conditional-view-processing/"},"next":{"docname":"topics/signing","title":"暗号署名","url":"/ja/6.0/topics/signing/"},"formats":{"html":"/ja/6.0/topics/composite-primary-key/","markdown":"/ja/6.0/topics/composite-primary-key.md","json":"/ja/6.0/topics/composite-primary-key.json"},"source":"https://github.com/django/django/blob/stable/6.0.x/docs/topics/composite-primary-key.txt","official":"https://docs.djangoproject.com/ja/6.0/topics/composite-primary-key/","inVersions":["6.1","6.0","5.2"],"inLocales":["en","sv","zh-hans","ga","fr","ja","id","it","pt-br","ko","es","el","pl"]}