رابطه‌های چندبه‌چند (Many‑to‑Many) در Django: آموزش کامل با مثال‌های عملی

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

ManyToManyField، رابطه چندبه‌چند، Django ORMarticle_set، add، remove، set، clearکوئری‌زدن رابطه‌ها

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

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

برای تعریف رابطهٔ many-to-many از ManyToManyField استفاده می‌کنیم. در مثال زیر، یک Article می‌تواند در چند Publication منتشر شود و هر Publication نیز چند Article دارد.


class Publication(models.Model):
    title = models.CharField(max_length=30)

class Article(models.Model):
    headline = models.CharField(max_length=100)
    publications = models.ManyToManyField(Publication)

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

ایجاد Publication:


p1 = Publication(title="The Python Journal"); p1.save()
p2 = Publication(title="Science News"); p2.save()
p3 = Publication(title="Science Weekly"); p3.save()

ایجاد Article:


a1 = Article(headline="Django lets you build web apps easily")

تا زمانی که Article ذخیره نشده باشد، نمی‌توان رابطهٔ M2M را تنظیم کرد:


a1.publications.add(p1)  # خطا

پس ابتدا ذخیره می‌کنیم:


a1.save()
a1.publications.add(p1)

۳. افزودن چند رابطه


a2 = Article(headline="NASA uses Python"); a2.save()
a2.publications.add(p1, p2)
a2.publications.add(p3)

افزودن تکراری مشکلی ندارد:


a2.publications.add(p3)  # تکراری → نادیده گرفته می‌شود

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


a2.publications.add(a1)  # TypeError

۴. ایجاد و افزودن در یک مرحله


new_pub = a2.publications.create(title="Highlights for Children")

۵. دسترسی به رابطه‌ها

از سمت Article:


a1.publications.all()
a2.publications.all()

از سمت Publication (سمت معکوس):


p1.article_set.all()
p2.article_set.all()

۶. کوئری‌زدن روی رابطهٔ M2M

جستجو با id یا pk:


Article.objects.filter(publications__id=1)
Article.objects.filter(publications=p1)

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


Article.objects.filter(publications__title__startswith="Science")

برای جلوگیری از تکرار:


Article.objects.filter(publications__title__startswith="Science").distinct()

جستجو با لیست:


Article.objects.filter(publications__in=[p1, p2]).distinct()

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


Publication.objects.filter(article__headline__startswith="NASA")
Publication.objects.filter(article__in=[a1, a2]).distinct()

۸. حذف از رابطه

حذف از سمت Article:


a4.publications.remove(p2)

حذف از سمت Publication:


p2.article_set.remove(a5)

۹. set و clear

تنظیم مجموعهٔ رابطه:


a4.publications.set([p3])

پاک‌کردن همهٔ رابطه‌ها:


a4.publications.clear()
p2.article_set.clear()

۱۰. رفتار هنگام حذف آبجکت‌ها

حذف Publication:


p1.delete()
a1.publications.all()  # خالی

حذف Article:


a2.delete()
p2.article_set.all()  # خالی

۱۱. Bulk delete و رفتار رابطه‌ها

حذف گروهی Publication:


Publication.objects.filter(title__startswith="Science").delete()
a2.publications.all()  # فقط موارد باقی‌مانده

حذف گروهی Article:


q = Article.objects.filter(headline__startswith="Django")
q.delete()
q.all()  # خالی

جمع‌بندی

رابطهٔ ManyToMany در Django یکی از قدرتمندترین ابزارهای ORM است. با استفاده از متدهای add، remove، set، clear و create می‌توان رابطه‌ها را به‌صورت کامل مدیریت کرد. همچنین Django امکان کوئری‌زدن از هر دو سمت رابطه را فراهم می‌کند و رفتار رابطه‌ها هنگام حذف آبجکت‌ها کاملاً قابل پیش‌بینی است.

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