مقدمه


در این بخش، به بررسی سایر عملیات اساسی مدیریت داده‌ها CRUD در برنامه‌های تحت وب، یعنی نحوه‌ی ایجاد (Create)، ویرایش (Update) و حذف (Delete) داده‌های یک مدل می‌پردازیم.

در قسمت پایانی بخش قبلی، فرآیند خواندن (Read) داده‌ها را بررسی کردیم. در آن مثال، با کلیک روی نام پروژه به مسیر read-project/ هدایت می‌شدیم و جزئیات هر پروژه نمایش داده می‌شد. این فرآیند، تنها یک‌طرفه بود: داده‌ها از پایگاه داده خوانده و به کاربر نمایش داده می‌شدند، اما هیچ امکانی برای ارسال یا تغییر داده وجود نداشت.

برای پیاده‌سازی سایر عملیات CRUD که در بالا اشاره شد، نیازمند یک مکانیزم برای دریافت ورودی از کاربر و ارسال آن به سرور هستیم. در دنیای وب، این وظیفه به‌عهده‌ی فرم‌ها (Forms) است. در فریم‌ورک جنگو نیز، فرم‌ها نقش کلیدی در انتقال داده‌ها بین تمپلیت‌ها (صفحات HTML) و پایگاه داده ایفا می‌کنند.


مفهوم فرم در HTML

در HTML، یک Form شامل مجموعه‌ای از فیلدها یا ویجت‌ها (widgets) است که برای دریافت داده از کاربر و ارسال آن به سرور استفاده می‌شود. فرم‌ها ابزارهایی انعطاف‌پذیر هستند که امکان جمع‌آوری انواع داده‌ها را از طریق المان‌هایی مانند text box، checkbox، radio button، انتخاب‌گر تاریخ و... فراهم می‌کنند.

علاوه بر جمع‌آوری داده، فرم‌ها می‌توانند داده‌ها را در قالب درخواست‌های POST ارسال کنند و از طریق مکانیزم‌های امنیتی مانند توکن CSRF (Cross-Site Request Forgery protection) که امنیت نسبی بالایی دارند از حملات امنیتی رایج جلوگیری می‌کنند. این توکن به‌صورت خودکار توسط جنگو در فرم‌ها قرار داده می‌شود و اطمینان حاصل می‌کند که درخواست‌ها واقعا از طرف کاربر معتبر ارسال شده‌اند.

اگرچه تاکنون به‌صورت مستقیم فرمی ایجاد نکرده‌ایم، اما در رابط مدیریت جنگو (Admin Interface) هنگام افزودن پروژه‌ها، در واقع در پس‌زمینه از یک فرم مبتنی بر مدل Project استفاده می‌شد.


سیستم فرم در جنگو

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

اصلی‌ترین بخش این سیستم، کلاس Form است. جنگو دو نوع فرم ارائه می‌دهد

  1. Form — برای ساخت فرم‌های سفارشی که لزوما به یک مدل متصل نیستند. به‌عنوان مثال، فرم‌های تماس یا جستجو که داده‌هایشان مستقیما در پایگاه داده ذخیره نمی‌شوند.

  2. ModelForm — برای ساخت فرم‌هایی که مستقیما مبتنی بر یک مدل جنگو بوده و به‌صورت خودکار فیلدهای مدل را به المان‌های فرم تبدیل می‌کند و تمامی ویژگی‌های مرتبط — از جمله نوع ورودی (ویجت)، برچسب‌ها، مقادیر پیش‌فرض، محدودیت‌ها و پیام‌های خطا — را مدیریت می‌کند.

در اغلب مواقع، از ModelForm به‌ویژه هنگام پیاده‌سازی عملیات CRUD، از ModelForm استفاده می‌شود، چرا که توسعه را سریع‌تر، ایمن‌تر و کم‌خطا‌تر می‌کند.


تعریف یک ModelForm

تعریف ModelForm بسیار ساده است و حداقل به دو بخش نیاز دارد:

  • مدل مرجعی که فرم بر اساس آن ساخته می‌شود ← model

  • لیستی از فیلدهایی از مدل که باید در فرم نمایش داده شوند. ← fields

به‌طور متعارف، فرم‌ها در یک فایل جداگانه با نام forms.py در دایرکتوری اپلیکیشن تعریف می‌شوند. این فایل به‌صورت پیش‌فرض در ساختار پروژه‌ی جنگو وجود ندارد و باید به‌صورت دستی ایجاد شود.

 

coreapp/forms.py

from django.forms import ModelForm
from .import models

class ProjectForm(ModelForm):
    class Meta:
        model = models.Project
        fields = ['title', 'area', 'content', 'tags', ]
  • کلاس ProjectForm از ModelForm ارث‌بری می‌کند.
  • در بخش Meta، مدل مرجع (Project) و فیلدهای مورد نظر برای نمایش در فرم مشخص شده‌اند.
  • جنگو به‌صورت خودکار برای هر فیلد، المان HTML مناسب (ویجت) را بر اساس نوع داده‌ی تعریف‌شده در مدل تولید می‌کند. مثلا یک فیلد CharField به یک <input type="text"> تبدیل می‌شود، در حالی که یک TextField به یک <textarea> تبدیل می‌گردد.
💡 نکته مهم: نام کلاس فرم معمولاً با حرف بزرگ شروع می‌شود (مثلاً ProjectForm) تا با قراردادهای نام‌گذاری پایتون (PascalCase) هماهنگ باشد.

 

همانطور که ملاحظه می‌شود، می‌توان سطح مدل را برای مدل خود و با اجرای کلاس Meta، تعیین نمود.

بسیاری از گزینه‌های دیگر matadata کنترل می‌کنند که کدام پایگاه‌ داده باید برای مدل مورد استفاده قرار گیرد تا بتوان داده‌ها را ذخیره کرد.

فرآیندی که در بالا جریان می‌­یابد بدین صورت است که جنگو model مورد اشاره در دستور کد را فراخوانی کرده و فرمی با فیلدهای مورد اشاره در قسمت fields مبتنی بر نوع داده­‌های (Data Types) تعریف شده در مدل می­‌سازد.


همچنین برای اطلاع دادن به جنگو برای ساختن فرمی با تمامی فیلدهای تعریف شده در مدل می‌توان از __all__ در قسمت fields استفاده کرد.

fields = '__all__'

نکته: باید توجه داشت که فیلد­هایی همانند create و id که به­‌صورت پیش‌فرض مقداردهی می­شوند و یا فیلدهایی که پارامتر editable = False داشته باشند در فرم ایجاد شده قرار نخواهند داشت.