رابطه یک به چند - ForeignKey
در سیستمهای مدیریت پایگاهدادههای رابطهای و بهویژه در چارچوب جنگو، رابطه ForeignKey
ابزاری بنیادین برای ایجاد ارتباط جهتدار بین دو مدل محسوب میشود که از نظر منطقی معادل یک رابطهٔ یک به چند (One-to-Many) است. این بدان معناست که یک رکورد در مدل والد — مثلاً User
— میتواند با چندین رکورد در مدل فرزند — مثلاً Project
— مرتبط باشد، در حالی که هر رکورد در مدل فرزند تنها میتواند به یک رکورد منحصربهفرد در مدل والد ارجاع دهد. این الگو در مثالهای واقعی مانند «مسئولیت یک کاربر بر چندین پروژه، در حالی که هر پروژه تنها یک مسئول دارد» به خوبی قابل مشاهده است. • از دید مدل فرزند (Project
)، همین رابطه بهعنوان چند به یک (ManyToOne) تفسیر میشود، زیرا چندین رکورد در این مدل به یک رکورد واحد در مدل والد اشاره میکنند.
این دوگانگی در نامگذاری رابطه — OneToMany
از دید والد و ManyToOne
از دید فرزند — گاهی برای توسعهدهندگان مبتدی گیجکننده است، اما درک دقیق آن شرط لازم برای طراحی صحیح مدلها و دسترسی کارآمد به دادههای مرتبط در لایه منطق کسبوکار است.
در پیادهسازی، فیلد ForeignKey
همواره در مدل فرزند تعریف میگردد و به مدل والد متصل میشود — چرا که در سطح پایگاهداده، این مدل فرزند است که نیازمند ارجاع به اطلاعات مدل والد خواهد بود. در واقع، فرآیندی که در سطح پایگاهداده اتفاق میافتد به این صورت است که هنگام تعریف یک فیلد ForeignKey
در مدل فرزند، یک ستون جدید (مثلاً owner_id
) به صورت خودکار در جدول مربوط به مدل فرزند اضافه میشود که به کلید اصلی مدل والد (User
) اشاره میکند.
coreapp/models.py
from django.db import models
from django.contrib.auth.models import User
import uuid
class project(models.Model):
owner = models.ForeignKey(User, on_delete=models.CASCADE, related_name="projects")
title = models.CharField(max_length=200)
subject = models.CharField(max_length=500)
content = models.TextField(null=True, blank=True)
demo = models.URLField(null=True, blank=True)
created = models.DateTimeField(auto_now_add=True)
id = models.UUIDField(default=uuid.uuid4, unique=True, primary_key=True, editable=False)
def __str__(self):
return self.title
در مدل Project
که در کد فوق تعریف شده است، رابطهٔ ForeignKey
از طریق فیلد owner
به مدل User
(از اپ django.contrib.auth
) متصل شده است که مدل پیشفرض جنگو بوده و هنگام ایجاد کاربری superuser شرح مختصری از آن رفت. این تعریف بهصورت دقیق یک رابطه چند به یک (ManyToOne) را از دید مدل Project
پیادهسازی میکند — یعنی هر پروژه تنها میتواند یک مالک (owner
) داشته باشد، اما یک کاربر میتواند مالک چندین پروژه باشد. این رابطه در سطح پایگاهداده با افزودن یک ستون owner_id
در جدول project
پیادهسازی میشود که به کلید اصلی (id
) جدول auth_user
اشاره میکند.
⚠️ پارامتر on_delete=models.CASCADE
تعیین میکند که در صورت حذف کاربر، تمام پروژههای مرتبط با او نیز بهصورت خودکار حذف خواهند شد — رفتاری که در بسیاری از سیستمها برای حفظ تمامیت دادهها منطقی و مطلوب است.
⚠️ در جنگو، برای دسترسی معکوس — یعنی از مدل والد به مدل فرزند — از ویژگی related_name
استفاده میشود که در زمان تعریف ForeignKey
اختیاری اما بسیار توصیهشده است. این ویژگی امکان تعریف یک نام معنادار برای دسترسی به مجموعهٔ رکوردهای مرتبط را فراهم میکند
⚠️ برای بازتاب این تغییرات در ساختار پایگاهداده، الزامی است که دو دستور makemigrations
و migrate
به ترتیب اجرا شوند