Django ORMでForeignKey(外部キー)を持つモデルにデータを追加する方法を解説します。紐づいたモデルがある場合のデータ作成には、いくつかのパターンがあります。
モデルの準備
まず、1対多のリレーションを持つモデルを定義します。
from django.db import models
class Company(models.Model):
name = models.CharField(max_length=100)
class Meta:
verbose_name = "会社"
class Employee(models.Model):
name = models.CharField(max_length=100)
company = models.ForeignKey(Company, on_delete=models.CASCADE)
class Meta:
verbose_name = "社員"EmployeeモデルがCompanyモデルへのForeignKeyを持っています。これは「社員は1つの会社に所属する」というリレーションです。
基本的なデータ作成(外部キーIDを指定)
最もシンプルな方法は、ForeignKeyのフィールド名に_idを付けてIDを直接指定する方法です。
from .models import Company, Employee
def create_employee(request):
# company_idを直接指定してEmployeeを作成
Employee.objects.create(name="山田太郎", company_id=1)# Employeeテーブルに以下のレコードが追加される
# id=1, name="山田太郎", company_id=1company_id=1と指定することで、idが1のCompanyに紐づくEmployeeが作成されます。
オブジェクトを指定する方法
外部キーのIDではなく、関連オブジェクト自体を渡すこともできます。
# Companyオブジェクトを取得してから指定
company = Company.objects.get(id=1)
Employee.objects.create(name="山田太郎", company=company)Djangoが自動的にオブジェクトからIDを取得して外部キーに設定します。前の例と結果は同じです。
逆参照を使った作成
親モデル(Company)側から子モデル(Employee)を作成することもできます。
company = Company.objects.get(id=1)
# 逆参照マネージャを使って作成
company.employee_set.create(name="佐藤花子")
# related_nameを設定している場合はそのまま使える
# 例: company = models.ForeignKey(Company, on_delete=models.CASCADE, related_name='employees')
# company.employees.create(name="佐藤花子")この方法では、company_idを明示的に指定する必要がなく、自動的に紐づけが行われます。
save()を使った作成
create()を使わず、インスタンスを作成してからsave()する方法もあります。
company = Company.objects.get(id=1)
# インスタンスを作成してからsave
employee = Employee(name="鈴木一郎", company=company)
employee.save()
# または company_idで指定
employee = Employee(name="鈴木一郎", company_id=1)
employee.save()バリデーションを行ってから保存したい場合や、保存前に追加の処理を行いたい場合に便利です。
実践的な使用例(フォームからの登録)
ビューでフォームからのデータを受け取って関連モデルを作成する実践例です。
from django.shortcuts import redirect, render
from .models import Company, Employee
def create_employee(request):
if request.method == 'POST':
name = request.POST.get('name')
company_id = request.POST.get('company_id')
# 会社が存在するか確認してから作成
if Company.objects.filter(id=company_id).exists():
Employee.objects.create(
name=name,
company_id=company_id
)
return redirect('employee_list')
companies = Company.objects.all()
return render(request, 'employees/create.html', {
'companies': companies
})create()は内部でsave()を呼び出すため、1行でインスタンスの作成と保存が同時に行われます。一方、Employee()でインスタンスを作成しただけではデータベースには保存されないため、必ずsave()を呼ぶ必要があります。
ForeignKeyのon_deleteパラメータは必須です。親レコードが削除された場合の動作を指定します。CASCADE(一緒に削除)、PROTECT(削除を防ぐ)、SET_NULL(NULLに設定、null=True必須)などがあります。
まとめ
company_id=1のようにForeignKeyのIDを直接指定して作成できる- 関連オブジェクトを取得して
company=company_objのように渡すこともできる - 親モデルの
employee_set.create()で逆参照から作成できる create()は作成と保存を同時に行い、save()は分離して実行できる- フォームからの登録時は、存在確認を行ってからデータを作成するのが安全