تایپ‌های فیلد


وقتی در فریمورک جنگو شروع به ساخت مدل‌های داده‌ای می‌کنیم، اولین و مهم‌ترین تصمیمی که باید بگیریم، انتخاب تایپ فیلد (Field Type) مناسب برای هر ستون داده است. فیلدها در جنگو نه‌تنها ساختار داده‌ها را در پایگاه داده مشخص می‌کنند، بلکه نحوه نمایش، اعتبارسنجی، ذخیره‌سازی و حتی رفتار در فرم‌ها و پنل ادمین را نیز تعیین می‌کنند. در این بخش، به بررسی تمامی انواع رایج و پیشرفته فیلدهای جنگو می‌پردازیم — از ساده‌ترین‌ها تا فیلدهای رابطه‌ای و سفارشی.

در تعریف مدل اشاره شد که هر مدل (Model) یک کلاس پایتونی است که از django.db.models.Model ارث‌بری می‌کند. هر فیلد در این کلاس نیز، یک ویژگی (attribute) است که نمونه‌ای از یکی از کلاس‌های موجود در django.db.models را نگه می‌دارد — مثل CharField یا ForeignKey.

فیلدها ...

  • در زمان اجرای makemigrations و migrate به ستون‌های جدول در دیتابیس تبدیل می‌شوند.
  • در فرم‌های خودکار (ModelForm) و پنل ادمین، ویجت‌های مناسب را ایجاد می‌کنند.
  • اعتبارسنجی داده‌ها را بر اساس نوع و پارامترها انجام می‌دهند.
  • امکان اعمال محدودیت‌های دیتابیسی (مثل UNIQUE, NOT NULL) را فراهم می‌کنند.

انتخاب نوع صحیح فیلد، تأثیر مستقیمی بر کارایی، صحت داده‌ها و تجربه کاربری خواهد داشت.

🧱 دسته‌بندی کلی فیلدها

فیلدهای جنگو را می‌توان به چند دسته کلی تقسیم کرد:

    1. فیلدهای اسکالر (مقادیر ساده) — مثل متن، عدد، تاریخ
    2. فیلدهای رابطه‌ای — برای اتصال مدل‌ها به هم
    3. فیلدهای ساختاریافته و خاص — مثل فایل، تصویر، JSON
    4. فیلدهای عمومی و کمکی — مثل AutoField, GenericIPAddressField

در ادامه، هر دسته را به‌صورت جزء به جزء بررسی می‌کنیم.

فیلدهای اسکالر (Scalar Fields)


فیلدهای اسکالر، ساده‌ترین و رایج‌ترین نوع فیلدها هستند که مقادیر ساده را ذخیره می‌کنند — یعنی هر فیلد فقط یک مقدار ساده (مثل متن، عدد، تاریخ یا بولین) را نگه می‌دارد. این فیلدها مستقیماً به ستون‌های ساده در دیتابیس تبدیل می‌شوند.

الف) فیلدهای متنی:
    • CharField: برای رشته‌های کوتاه با طول مشخص (max_length اجباری است).
    • TextField: برای متن‌های بلند — بدون محدودیت طول.
    • EmailField: اعتبارسنجی ایمیل + محدودیت طول.
    • SlugField: برای URLها — فقط حروف، اعداد، خط تیره و زیرخط.
    • URLField: اعتبارسنجی آدرس اینترنتی.
 
ب) فیلدهای عددی:
    • IntegerField, BigIntegerField, SmallIntegerField: اعداد صحیح با دامنه‌های مختلف.
    • PositiveIntegerField, PositiveSmallIntegerField: فقط اعداد مثبت.
    • DecimalField: اعداد اعشاری با دقت بالا — مناسب امور مالی.
    • FloatField: اعداد اعشاری با دقت متوسط (با خطای گرد کردن).
 
ج) فیلدهای تاریخ و زمان:
    • DateField: فقط تاریخ (YYYY-MM-DD)
    • DateTimeField: تاریخ + زمان (YYYY-MM-DD HH:MM:SS)
    • TimeField: فقط زمان (HH:MM:SS)
 
د) فیلدهای بولی:
    • BooleanField:  مقدار True و یا False

 

class Sample(models.Model):
    name = models.CharField(max_length=200)
    price = models.DecimalField(max_digits=10, decimal_places=2)
    created_at = models.DateTimeField(auto_now_add=True)
    is_available = models.BooleanField(default=True)

 

فیلدهای رابطه‌ای (Relational Fields)


این فیلدها برای ایجاد رابطه بین مدل‌ها استفاده می‌شوند و در پایگاه داده به صورت کلید خارجی (Foreign Key) یا جدول واسط (Intermediate Table) پیاده‌سازی می‌شوند. مدل‌های جنگو به طور پیش‌فرض از RDBMSها استفاده می‌کنند که روابط بین مدل‌ها رو پشتیبانی می‌کند. استفاده از روابط در پایگاه داده باعث بهبود عملکرد، جلوگیری از تکرار داده و ایجاد ساختار رابطه‌ای بین داده‌ها می‌شود.

 

الف) ForeignKey — رابطه یک به چند
    • یک رکورد در مدل A به چند رکورد در مدل B اشاره می‌کند. (مثال: یک نویسنده — چند مقاله)
    • on_delete اجباری است — تعیین می‌کند در صورت حذف رکورد والد چه اتفاقی بیفتد.

 

ب) OneToOneField — رابطه یک به یک
    • یک رکورد در مدل A فقط به یک رکورد در مدل B متصل است. (مثال: کاربر — پروفایل کاربری.)
 
ج) ManyToManyField — رابطه چند به چند
    • چند رکورد در مدل A به چند رکورد در مدل B متصل می‌شوند. (مثال: مقاله — تگ‌ها).

 

class Smaple(models.Model):
    author = models.ForeignKey('Author', on_delete=models.CASCADE)
    profile = models.OneToOneField('UserProfile', on_delete=models.CASCADE)
    tags = models.ManyToManyField('Tag', blank=True)

 

در بخش روابط مدل‌ها، به‌صورت مفصل و با جزئیات کاربردی به این مفهوم کلیدی خواهیم پرداخت که چگونه می‌توان با استفاده از فیلدهای رابطه‌ای جنگو — مانند ForeignKey، OneToOneField و ManyToManyField — ساختاری منسجم، پایدار و بدون تکرار داده طراحی کرد. این فیلدها نه‌تنها در سطح کد پایتون، بلکه در عمق پایگاه داده نیز با ایجاد کلیدهای خارجی یا جداول واسط، روابط معنادار بین موجودیت‌ها را پیاده‌سازی می‌کنند. هدف نهایی این است که از ذخیره‌سازی تکراری و غیرضروری داده‌ها جلوگیری شود و هر اطلاعاتی فقط در یک نقطه منحصربه‌فرد نگهداری شود — تا در صورت نیاز به به‌روزرسانی، تنها یک تغییر کافی باشد و تمام بخش‌های مرتبط به‌طور خودکار و بدون خطا بازتابی از آن تغییر ارائه دهند. این رویکرد، پایهٔ اصلی یکپارچگی داده‌ها (Data Integrity) و مقیاس‌پذیری سیستم است و درک عمیق آن، یک توسعه‌دهنده معمولی را به یک معمار داده حرفه‌ای تبدیل می‌کند. 

فیلدهای ساختاریافته و خاص (Structured & Specialized Fields)


این فیلدها برای ذخیره داده‌های مرکب، باینری یا رسانه‌ای طراحی شده‌اند. برخلاف فیلدهای اسکالر، این فیلدها ممکن است شامل چند بخش باشند یا نیاز به پردازش خاصی (مثل آپلود فایل یا تجزیه JSON) داشته باشند.

الف) FileField و ImageField
    • برای آپلود فایل و تصویر.
    • نیاز به تنظیم MEDIA_URL و MEDIA_ROOT در فایل تنظیمات پروژه settings.py دارند.
    • ImageField نیازمند کتابخانه Pillow است.

 

ب) JSONField
    • برای ذخیره داده‌های JSON — بسیار منعطف.
    • پشتیبانی از کوئری‌های داخل JSON در دیتابیس‌های مدرن (مثل PostgreSQL).
    • مناسب برای: تنظیمات پویا، لاگ‌های ساختاریافته، داده‌های متغیر بین رکوردها.
 
ج) ArrayField (فقط در PostgreSQL)
    • ذخیره لیستی از مقادیر (مانند لیست تلفن‌های یک کاربر).
    • فقط در PostgreSQL پشتیبانی می‌شود.
 
class Smaple(models.Model):
    avatar = models.ImageField(upload_to='avatars/')
    resume = models.FileField(upload_to='resumes/')
    metadata = models.JSONField(default=dict)
    phones = models.ArrayField(models.CharField(max_length=10))
 
د) HStoreField (فقط در PostgreSQL — قدیمی‌تر)
    • ذخیره داده‌های key-value — جایگزین قدیمی‌تر برای JSONField.

فیلدهای عمومی و کمکی (Generic & Helper Fields)


این فیلدها معمولاً برای مدیریت زیرساخت مدل یا ذخیره اطلاعات سیستمی استفاده می‌شوند. بعضی از آن‌ها به‌صورت خودکار توسط جنگو ایجاد می‌شوند (مثل id) و بعضی برای موارد خاص طراحی شده‌اند.

الف) AutoField / BigAutoField
    • فیلد عددی که به‌صورت خودکار افزایش می‌یابد.
    • معمولاً به عنوان id پیش‌فرض در هر مدل بصورت خودکار توسط جنگو استفاده می‌شود و نیازی به تعریف دستی ندارد.
ب) UUIDField
    • ذخیره شناسه‌های منحصربه‌فرد جهانی.
    • مناسب برای مواردی که id عددی قابل حدس نباشد.
    • نیازمند بکارگیری کتابخانه uuid است.

 

ج) GenericIPAddressField
    • ذخیره آدرس IP (هم IPv4 و هم IPv6).

 

د) BinaryField
    • ذخیره داده‌های باینری خام — مثل فایل‌های رمزگذاری شده یا بایت‌ها.
    • محدودیت در استفاده در فرم‌ها و فیلترها دارد.
import uuid

class smaple(models.Model):
    id = models.BigAutoField(primary_key=True)
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    ip_address = models.GenericIPAddressField()
    encrypted_data = models.BinaryField()

 

هـ) GenericForeignKey (از django.contrib.contenttypes)
    • برای ایجاد رابطه به مدل‌های مختلف — مکانیزم “Generic Relation” (مانند سیستم کامنت که برای مدل‌های مقاله، محصول و ...  کار کند).
    • نیازمند دو فیلد کمکی (content_type و object_id) است.
    • content_type: مشخص می‌کند که رکورد مربوط به کدام مدل است (مثلاً Article یا Product)
    • object_id: مشخص می‌کند که رکورد مربوط به کدام id از آن مدل است
    • content_object: یک فیلد مجازی (غیر فیزیکی) که به شما اجازه می‌دهد مستقیماً به شیء مرتبط دسترسی داشته باشید.
from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType

class Comment(models.Model):
    content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE) # Refer to Model (Article, Product, ...)    
    object_id = models.UUIDField()                                          # Refer to Model.Object.id  
    content_object = GenericForeignKey('content_type', 'object_id')         # "content_type" & "object_id" Combination to access the object directly

    comment = models.TextField()
    created = models.DateTimeField(auto_now_add=True)

⚠️ اگر در مدل مقصد (مثلاً Article) از UUIDField به عنوان id بجای AutoField پیش‌فرض جنگو استفاده گردد، باید فیلد object_id در مدل Comment نیز از PositiveIntegerField به UUIDField تغییر داده شود — در غیر این صورت، با خطا مواجه خواهیم شد.