کلیدهای اصلی مرکب (Composite Primary Keys) در Django 5.2: راهنمای کامل

این مقاله ویژگی جدید کلیدهای اصلی مرکب در Django 5.2 را توضیح می‌دهد. موضوعاتی مانند تعریف CompositePrimaryKey، مقداردهی pk به‌صورت tuple، محدودیت‌های مهاجرت، روابط، فرم‌ها، توابع پایگاه‌داده و نحوهٔ شناسایی کلیدهای مرکب با _meta.pk_fields بررسی می‌شوند.

CompositePrimaryKey، کلید مرکب جنگوDjango 5.2، کلید اصلی چندستونهForeignObject، pk_fields

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

مقدمه

در جنگو، هر مدل یک کلید اصلی (Primary Key) دارد که به‌طور پیش‌فرض یک فیلد تکی است. اما در برخی طراحی‌های پایگاه‌داده، لازم است کلید اصلی از چند فیلد تشکیل شود. از Django 5.2 به بعد، جنگو از کلیدهای اصلی مرکب پشتیبانی می‌کند.


تعریف Composite Primary Key

برای تعریف کلید مرکب، کافی است در مدل، ویژگی pk را برابر CompositePrimaryKey قرار دهید:


class OrderLineItem(models.Model):
    pk = models.CompositePrimaryKey("product_id", "order_id")
    product = models.ForeignKey(Product, on_delete=models.CASCADE)
    order = models.ForeignKey(Order, on_delete=models.CASCADE)
    quantity = models.IntegerField()

این کار باعث می‌شود جنگو در دیتابیس کلید اصلی مرکب ایجاد کند:


PRIMARY KEY (product_id, order_id)

ساختار pk در کلیدهای مرکب

در مدل‌هایی با کلید مرکب، مقدار pk یک tuple است:


item.pk
# (1, "A755H")

می‌توانید pk را مستقیماً مقداردهی کنید:


item = OrderLineItem(pk=(2, "B142C"))
item.product_id  # 2
item.order_id    # "B142C"

فیلتر کردن نیز با tuple انجام می‌شود:


OrderLineItem.objects.filter(pk=(1, "A755H")).count()

محدودیت‌ها و وضعیت توسعه

پشتیبانی از کلیدهای مرکب هنوز کامل نیست. در حال حاضر موارد زیر پشتیبانی نمی‌شوند:

  • ForeignKey به مدل دارای کلید مرکب
  • GenericForeignKey
  • ثبت مدل در Django Admin

این قابلیت‌ها در نسخه‌های آینده اضافه خواهند شد.


مهاجرت به کلید مرکب

جنگو نمی‌تواند یک جدول موجود را از کلید تکی به کلید مرکب مهاجرت دهد. همچنین نمی‌تواند فیلدی را به کلید مرکب اضافه یا حذف کند.

برای مهاجرت:

  1. ابتدا در دیتابیس، کلید مرکب را به‌صورت دستی ایجاد کنید.
  2. سپس در مدل، CompositePrimaryKey را اضافه کنید.
  3. مهاجرت‌های مربوطه را با --fake اعمال کنید.
  4. یا از SeparateDatabaseAndState استفاده کنید.

کلیدهای مرکب و روابط

ForeignKey نمی‌تواند به مدل دارای کلید مرکب اشاره کند:


class Foo(models.Model):
    item = models.ForeignKey(OrderLineItem)  # ❌ پشتیبانی نمی‌شود

راه‌حل: ForeignObject

می‌توانید از ForeignObject استفاده کنید:


class Foo(models.Model):
    item_order_id = models.CharField(max_length=20)
    item_product_id = models.IntegerField()
    item = models.ForeignObject(
        OrderLineItem,
        on_delete=models.CASCADE,
        from_fields=("item_order_id", "item_product_id"),
        to_fields=("order_id", "product_id"),
    )

توجه: ForeignObject یک API داخلی است و شامل محدودیت‌ها و ریسک‌های خودش است.


کلیدهای مرکب و توابع پایگاه‌داده

بسیاری از توابع پایگاه‌داده فقط یک ستون را می‌پذیرند:


Max("order_id")      # OK
Max("product_id")    # OK
Max("pk")            # ❌ ValueError
Count("pk")          # OK

زیرا pk شامل چند ستون است.


کلیدهای مرکب در فرم‌ها

چون pk یک فیلد واقعی نیست، در ModelForm ظاهر نمی‌شود:



اضافه کردن pk به فرم باعث FieldError می‌شود.

همچنین تغییر مقدار pk یک شیء موجود باعث ایجاد یک شیء جدید می‌شود. بنابراین بهتر است فیلدهای کلید اصلی را editable=False کنید.


اعتبارسنجی مدل با کلید مرکب

چون pk یک فیلد مجازی است، exclude={"pk"} در clean_fields() اثری ندارد. برای حذف از اعتبارسنجی، باید هر فیلد را جداگانه exclude کنید.

اما validate_unique() می‌تواند exclude={"pk"} داشته باشد.


تشخیص کلیدهای مرکب در کد

قبلاً می‌شد با بررسی field.primary_key کلید اصلی را پیدا کرد. اما در کلیدهای مرکب، هیچ فیلدی primary_key=True ندارد.

برای شناسایی کلیدهای مرکب از _meta.pk_fields استفاده کنید:


Product._meta.pk_fields
# []

OrderLineItem._meta.pk_fields
# [, ]

جمع‌بندی

کلیدهای اصلی مرکب در Django 5.2 یک قابلیت مهم برای پروژه‌هایی هستند که نیاز به کلیدهای چندستونه دارند. با وجود برخی محدودیت‌ها در روابط، فرم‌ها و مهاجرت‌ها، این ویژگی اکنون به‌صورت رسمی پشتیبانی می‌شود و امکان طراحی دیتابیس‌های پیچیده‌تر را فراهم می‌کند.

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

مقالات مرتبط

فریم‌ورک 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 گرفته تا دسریال‌سازی داده‌ها، سریال‌سازی فیلدهای انتخابی، کار با مدل‌های ارث‌بری، مدیریت روابط، و نکات مهم هنگام ذخیرهٔ داده‌های دسریال‌شده.

ادامه