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

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

OneToOneField، رابطه یک‌به‌یکDjango ORM، CASCADEreverse relation، waiter_set

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

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

برای تعریف رابطهٔ one‑to‑one از OneToOneField استفاده می‌کنیم. در مثال زیر، هر Place می‌تواند یک Restaurant داشته باشد، و هر Restaurant دقیقاً یک Place دارد.


class Place(models.Model):
    name = models.CharField(max_length=50)
    address = models.CharField(max_length=80)

class Restaurant(models.Model):
    place = models.OneToOneField(
        Place,
        on_delete=models.CASCADE,
        primary_key=True,
    )
    serves_hot_dogs = models.BooleanField(default=False)
    serves_pizza = models.BooleanField(default=False)

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

ایجاد Place:


p1 = Place(name="Demon Dogs", address="944 W. Fullerton"); p1.save()
p2 = Place(name="Ace Hardware", address="1013 N. Ashland"); p2.save()

ایجاد Restaurant:

در رابطهٔ یک‌به‌یک، کلید اصلی Restaurant همان Place است:


r = Restaurant(place=p1, serves_hot_dogs=True, serves_pizza=False)
r.save()

۳. دسترسی به رابطه

Restaurant → Place:


r.place

Place → Restaurant:


p1.restaurant

اگر Place رستوران نداشته باشد:


hasattr(p2, "restaurant")  # False

۴. تغییر رابطهٔ یک‌به‌یک

می‌توان Restaurant را به Place دیگری نسبت داد:


r.place = p2
r.save()
p2.restaurant  # اکنون رستوران p2 است

و دوباره برگرداند:


p1.restaurant = r
p1.restaurant

نکته مهم: Place باید ذخیره شده باشد


p3 = Place(name="Demon Dogs", address="944 W. Fullerton")
Restaurant.objects.create(place=p3, ...)  # ValueError

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

Restaurant → Place:


Restaurant.objects.get(place=p1)
Restaurant.objects.filter(place__name__startswith="Demon")
Restaurant.objects.exclude(place__address__contains="Ashland")

Place → Restaurant:


Place.objects.get(restaurant=r)
Place.objects.get(restaurant__place__name__startswith="Demon")

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

حذف Place باعث حذف Restaurant مرتبط می‌شود:


p2.delete()
Restaurant.objects.all()  # فقط رستوران p1 باقی مانده

۷. رابطه‌های جانبی: Waiter

در مثال، Waiter با Restaurant رابطهٔ ForeignKey دارد:


w = r.waiter_set.create(name="Joe")

کوئری‌زدن روی Waiter:


Waiter.objects.filter(restaurant__place=p1)
Waiter.objects.filter(restaurant__place__name__startswith="Demon")

جمع‌بندی

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

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