راهنمای کامل رابطه‌های چندبه‌یک (Many‑to‑One) در Django با استفاده از ForeignKey

این مقاله نحوهٔ تعریف و کار با رابطه‌های چندبه‌یک در Django را توضیح می‌دهد. از ایجاد آبجکت‌ها و دسترسی از هر دو سمت رابطه، تا جابه‌جایی رابطه‌ها، کوئری‌زدن روی فیلدهای مرتبط، استفاده از لیست و queryset در فیلترها، کوئری‌های حلقه‌ای، و رفتار حذف (CASCADE). تمام مفاهیم با مثال‌های واقعی از API پایتونی Django ارائه شده‌اند.

ForeignKey، رابطه چندبه‌یکDjango ORM، article_setCASCADE، کوئری رابطه‌ای

~2 دقیقه مطالعه · آخرین به‌روزرسانی ۱۹ اسفند ۱۴۰۴

۱. تعریف رابطهٔ چندبه‌یک در Django

برای تعریف رابطهٔ many‑to‑one از ForeignKey استفاده می‌کنیم. در مثال زیر، یک Reporter می‌تواند چندین Article داشته باشد، اما هر Article فقط یک Reporter دارد.


class Reporter(models.Model):
    first_name = models.CharField(max_length=30)
    last_name = models.CharField(max_length=30)
    email = models.EmailField()

class Article(models.Model):
    headline = models.CharField(max_length=100)
    pub_date = models.DateField()
    reporter = models.ForeignKey(Reporter, on_delete=models.CASCADE)

۲. ایجاد داده‌ها

ایجاد Reporter:


r = Reporter(first_name="John", last_name="Smith", email="[email protected]")
r.save()

r2 = Reporter(first_name="Paul", last_name="Jones", email="[email protected]")
r2.save()

ایجاد Article:


from datetime import date
a = Article(headline="This is a test", pub_date=date(2005, 7, 27), reporter=r)
a.save()

دسترسی به Reporter مرتبط:


a.reporter
a.reporter.id

ForeignKey نیاز به آبجکت ذخیره‌شده دارد

اگر Reporter ذخیره نشده باشد، خطا می‌دهد:


r3 = Reporter(first_name="John", last_name="Smith", email="[email protected]")
Article.objects.create(..., reporter=r3)  # ValueError

۳. دسترسی معکوس: Reporter → Article

Django به‌صورت خودکار یک مدیر معکوس به نام article_set ایجاد می‌کند:


r.article_set.all()

ایجاد Article از سمت Reporter:


new_article = r.article_set.create(
    headline="John's second story",
    pub_date=date(2005, 7, 29)
)

۴. جابه‌جایی Article بین Reporterها

می‌توان Article را به Reporter دیگر منتقل کرد:


r2.article_set.add(new_article2)
new_article2.reporter  # اکنون Paul Jones

افزودن نوع اشتباه خطا می‌دهد:


r.article_set.add(r2)  # TypeError

۵. کوئری‌زدن روی رابطهٔ ForeignKey

فیلتر روی فیلدهای Reporter:


Article.objects.filter(reporter__first_name="John")
Article.objects.filter(reporter__first_name="John", reporter__last_name="Smith")

فیلتر با pk یا آبجکت:


Article.objects.filter(reporter__pk=1)
Article.objects.filter(reporter=1)
Article.objects.filter(reporter=r)

استفاده از لیست یا queryset:


Article.objects.filter(reporter__in=[r, r2]).distinct()

Article.objects.filter(
    reporter__in=Reporter.objects.filter(first_name="John")
).distinct()

۶. کوئری از سمت معکوس (Article → Reporter)


Reporter.objects.filter(article__pk=1)
Reporter.objects.filter(article=a)
Reporter.objects.filter(article__headline__startswith="This").distinct()

count با distinct:


Reporter.objects.filter(article__headline__startswith="This").count()
Reporter.objects.filter(article__headline__startswith="This").distinct().count()

۷. کوئری‌های حلقه‌ای (Circular Queries)

می‌توان lookupها را بی‌نهایت زنجیره کرد:


Reporter.objects.filter(article__reporter__first_name__startswith="John").distinct()

۸. رفتار حذف (CASCADE)

چون on_delete=models.CASCADE استفاده شده، حذف Reporter باعث حذف Articleهای او می‌شود:


r2.delete()
Article.objects.all()  # مقالات مربوط به r2 حذف شده‌اند

حذف با JOIN:


Reporter.objects.filter(article__headline__startswith="This").delete()
Reporter.objects.all()  # خالی
Article.objects.all()   # خالی

جمع‌بندی

رابطهٔ چندبه‌یک در Django ساده اما بسیار قدرتمند است. با استفاده از ForeignKey می‌توان به‌راحتی بین آبجکت‌های مرتبط حرکت کرد، از هر دو سمت رابطه داده ایجاد کرد، رابطه‌ها را جابه‌جا کرد، و کوئری‌های پیچیده نوشت. Django با ایجاد مدیرهای معکوس و lookupهای قابل‌گسترش، کار با داده‌های رابطه‌ای را بسیار روان و کارآمد می‌کند.

نوشته و پژوهش‌شده توسط دکتر شاهین صیامی

مقالات مرتبط

فریم‌ورک Tasks در Django: راهنمای کامل اجرای کارهای پس‌زمینه در Django 6.0

Django 6.0 فریم‌ورک Tasks را معرفی کرده است؛ سیستمی داخلی برای تعریف و صف‌بندی کارهای پس‌زمینه خارج از چرخهٔ request–response. این مقاله نحوهٔ کار Tasks، پیکربندی backendها، تعریف و enqueue کردن Taskها، استفاده از context، و ادغام با سیستم‌های Worker خارجی را توضیح می‌دهد.

ادامه

پشتیبانی Asynchronous در Django: راهنمای کامل Async Views، ORM، Middleware، عملکرد و ایمنی

این مقاله پشتیبانی Django از برنامه‌نویسی غیرهم‌زمان (async) را توضیح می‌دهد. موضوعاتی مانند async views، اجرای Django تحت ASGI، رفتار middleware، قابلیت‌های ORM غیرهم‌زمان، sync_to_async، مدیریت قطع اتصال، نکات عملکردی، و مکانیزم‌های ایمنی Django برای جلوگیری از استفادهٔ ناامن async بررسی می‌شوند.

ادامه

System Check Framework در Django: راهنمای کامل نوشتن، ثبت، اجرا و تست چک‌های سیستمی

System Check Framework در Django مجموعه‌ای از بررسی‌های استاتیک برای تشخیص مشکلات رایج در پروژه است. این مقاله نحوهٔ اجرای چک‌ها، نوشتن چک‌های سفارشی، مدیریت پیام‌ها، برچسب‌گذاری چک‌ها، افزودن چک به مدل‌ها و فیلدها، و نوشتن تست‌های واحد و یکپارچه برای چک‌ها را توضیح می‌دهد.

ادامه

سیگنال‌ها در Django: راهنمای کامل استفاده، اتصال، ارسال و مدیریت Signalها

این مقاله سیستم سیگنال‌های Django را توضیح می‌دهد؛ مکانیزمی برای اطلاع‌رسانی رویدادها بین بخش‌های مختلف برنامه بدون ایجاد وابستگی مستقیم. موضوعاتی مانند نحوهٔ اتصال receiverها، استفاده از decorator، مدیریت senderهای خاص، محل مناسب قرارگیری کد سیگنال‌ها، هشدارهای مهم، و بهترین شیوه‌ها بررسی می‌شوند.

ادامه

آشنایی کامل با Django Settings: پیکربندی، مدیریت محیط، و بهترین شیوه‌ها

این مقاله یک راهنمای جامع دربارهٔ سیستم تنظیمات در Django ارائه می‌دهد. موضوعاتی مانند ساختار فایل تنظیمات، نحوهٔ تعیین DJANGO_SETTINGS_MODULE، استفاده از settings در کد، امنیت، پیکربندی دستی با configure()، استفادهٔ مستقل از Django با django.setup() و ایجاد تنظیمات سفارشی بررسی می‌شوند.

ادامه

سریال‌سازی و دسریال‌سازی در Django: راهنمای کامل کار با Serialization Framework

این مقاله سیستم سریال‌سازی Django را توضیح می‌دهد؛ از نحوهٔ تبدیل مدل‌ها به JSON، XML، YAML و JSONL گرفته تا دسریال‌سازی داده‌ها، سریال‌سازی فیلدهای انتخابی، کار با مدل‌های ارث‌بری، مدیریت روابط، و نکات مهم هنگام ذخیرهٔ داده‌های دسریال‌شده.

ادامه