ایجاد داده – Create
در این بخش، نحوه ایجاد یک صفحه برای ذخیره داده جدید (مثلاً یک پروژه جدید) در پایگاه داده با استفاده از مدل–فرمهای جنگو را بهصورت کامل و گامبهگام توضیح میدهیم. هدف ما این است که با استفاده از یک فرم هوشمند و ایمن، دادههای واردشده توسط کاربر را اعتبارسنجی کرده و در صورت صحیح بودن، در پایگاه داده ذخیره کنیم.
گام اول: ایجاد View برای نمایش فرم
اولین قدم، تعریف یک View در فایل views.py خواهد بود که فرم مربوطه را به کاربر نمایش دهد.
💡 نکته: در این مرحله فقط فرم را نمایش میدهیم. ذخیرهسازی داده در مرحله بعدی (با مدیریت درخواست POST) انجام میشود.
coreapp/views.py
from . import forms
def ProjectCreate(request):
projectForm = forms.ProjectForm()
context = {'form': projectForm }
return render(request, 'forms.html', context)
گام دوم: تعریف مسیر (URL) مربوط به View
حال باید یک الگوی مسیر (URL) برای دسترسی به View ایجاد شده، در فایل urls.py تعریف گردد.
coreapp/urls.py
urlpatterns = [
...,
path('project-add/', views.ProjectCreate, name='ProjectCreate'),
]
گام سوم: ایجاد تمپلیت عمومی برای فرمها
در مرحله پایانی به سراغ ایجاد تمپلیت عمومی forms.html در دایرکتوری ریشه پروژه خواهیم رفت. یکی از مزیتهای جنگو این است که میتوان یک تمپلیت عمومی برای تمام فرمهای ایجاد (Create) و ویرایش (Update) طراحی نمود. که تمامی مدلها را پوشش دهد. این کار از تکرار کد جلوگیری کرده و نیاز به ایجاد تمپلیتهای فرم متعدد برای مدلهای مختلف را — مگر در مواردی خاص — از بین میبرد.
tutorial/templates/forms.html
{% extends 'base.html' %}
{% block content %}
<form method="POST">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Save</button>
</form>
{% endblock %}
جنگو بهصورت پیشفرض از CSRF (Cross-Site Request Forgery) محافظت میکند. تگ {% csrf_token %} یک توکن امنیتی در فرم قرار میدهد که بدون آن، جنگو هر درخواست POST را رد کرده و خطای 403 Forbidden نمایش میدهد. همواره در هر فرمی که از method="POST" استفاده میکند، میبایست تگ {% csrf_token %} را قرار دهیم.
هنگام استفاده از تگ {{ form.as_p }}، جنگو بهصورت خودکار تمام فیلدهای فرم را بهصورت یک سری تگ <p> (پاراگراف) رندر میکند. هر فیلد در یک تگ <p> جداگانه قرار میگیرد که شامل برچسب (label) و ورودی (input) فیلد مربوطه خواهد بود و زمانی کاربردی خواهد بود که بخواهیم سریعا یک فرم قابل استفاده داشته باشیم (مثلا در مرحله توسعه یا پروتوتایپ) و نیازی به کنترل دقیق روی ظاهر فرم نداشته باشیم.
پس از اتمام مراحل، میتوان نمایشی از فیلدها را برای ایجاد پروژه جدید با رجوع به آدرس project-add/ در مرورگر، مشاهده کرد.

در پروژههای نهایی (production) که ظاهر کاربری مهم است و یا زمانی که نیاز به نمایش پیغامهای خطا (Errors)، متنهای راهنما (Help Text) یا استایلدهی پیشرفته داشته باشیم، بهتر است فرم عمومی forms.html را بهصورت دستی و با بهرهگیری از حلقه رندر کنیم.
tutorial/templates/forms.html
{% extends 'base.html' %}
{% block content %}
<form method="POST">
{% csrf_token %}
{% for field in form %}
<div class="mb-3">
{{ field.label_tag }}
{{ field }}
{% if field.help_text %}
<small>{{ field.help_text }}</small>
{% endif %}
{% if field.errors %}
<div>{{ field.errors }}</div>
{% endif %}
</div>
{% endfor %}
<button type="submit">Save</button>
</form>
{% endblock %}
تا به اینجا، تنها به نمایش تمپلیت فرم برای ایجاد پروژه در مدل Project توسط مدل–فرم ProjectForm پرداختیم. حال در ادامه میبایست به پردازش دادههای ارسالی از طریق فرم و ذخیره آنها در پایگاه داده بپردازیم که یکی از هستههای اصلی کار با فرمها در Django است
گام چهارم: پردازش و ذخیرهسازی دادهها
if request.method == 'POST':
data = forms.ProjectForm(request.POST)
if data.is_valid():
data.save()
return redirect('Projects')
— بررسی نوع درخواست
وقتی کاربر روی Submit فرم کلیک میکند، مرورگر یک درخواست HTTP از نوع POST به سرور ارسال میکند.. در view میبایست در ابتدای کار نوع درخواست ارسالی را توسط if request.method == 'POST' بررسی نمود. این بررسی، اولین سطح از منطق کنترل جریان پردازش و دخیرهسازی دادهها در View میباشد.
request.methodنشان میدهد که این درخواست از چه نوعی است (GE- فقط زمانی دادهها پردازش خواهند شد که درخواست از نوع
POSTباشد (یعنی کاربر، داده ارسال نموده باشد). T،POST،PUTو غیره).اگر درخواست از نوعGETباشد (مثلا وقتی کاربر صفحه را برای اولین بار باز میکند)، این بلوک اجرا نمیشود و معمولا یک فرم خالی نمایش داده میشود.
— ایجاد نمونه فرم با دادههای ارسالی
formData = ProjectForm(request.POST) فقط دادهها را دریافت و به فرم نسبت میدهیم — هنوز هیچ اعتبارسنجی یا ذخیرهسازی انجام نشده است.ProjectFormیک کلاس فرم است که ازforms.ModelFormارثبری کرده و مربوط به مدلProjectاست.request.POSTیک دیکشنری مانند (QueryDict) بوده که تمام دادههای ارسالی از طریق فرم (با متد POST) را در خود دارد.- با ارسال
request.POSTبه سازنده فرمProjectForm(...), جنگو یک نمونه پر شده از فرم ایجاد میکند که دادههای واردشده توسط کاربر را در خود نگه میدارد.
— اعتبارسنجی دادهها
اعتبارسنجی دادهها با متد is_valid() یکی از قدرتمندترین ویژگیهای جنگو است چرا که از خطاهای انسانی (مثل وارد کردن ایمیل نامعتبر) و حملات امنیتی (مثل تزریق داده — Data Injection ) جلوگیری میکند.
- تمام فیلدهای فرم را بر اساس قوانین تعریفشده در مدل یا فرم (مثل
max_length،required،validatorsو غیره) بررسی میکند.- اگر همه دادهها معتبر باشند:
- مقدار
Trueبرگردانده میشود. - دادههای تمیزشده (cleaned data) در ویژگی
formData.cleaned_dataقرار میگیرند.
- مقدار
- اگر حتی یک فیلد نامعتبر باشد:
- مقدار
Falseبرگردانده میشود. - خطاهای مربوطه در
formData.errorsذخیره میشوند و میتوان آنها را در تمپلیت نمایش داد.
- مقدار
- اگر همه دادهها معتبر باشند:
— ذخیره داده در پایگاه داده
اگر فرم معتبر باشد، از آنجا که ProjectForm یک ModelForm است، متد save() بهصورت خودکار:
- یک رکورد — Object — جدید از مدل
Projectایجاد میکند. - مقادیر فیلدها را از
cleaned_dataبه آن Object اختصاص میدهد. - Object را با فراخوانی
save()، در پایگاه داده ذخیره میکند (یک رکورد جدید در جدولprojectایجاد میشود).
forms.Form (نه ModelForm) ارثبری کرده بود، متد save() دیگر وجود نخواهد داشت و باید بهصورت دستی دادهها را در مدل ذخیره نمود.— هدایت مجدد کاربر
پس از ذخیره موفقیتآمیز داده، بهجای بازگرداندن یک صفحه جدید یا نمایش پیام، میتوان کاربر را به یک URL دیگر هدایت کرد. این کار با بهرهگیری از متد redirect , بر اساس الگوی طراحی معروف PRG (Post-Redirect-Get) انجام میشود.
چرا این کار مهم است؟
- جلوگیری از ارسال مجدد تصادفی فرم (اگر کاربر F5 بزند، دوباره داده ذخیره نمیشود).
- رفتار استاندارد و امن در وب.
- بهبود تجربه کاربری (مثلا هدایت به لیست پروژهها پس از ایجاد یک پروژه جدید).
redirect از مقداری که برای متغیر name — در اینجا name="Projects" — برای الگوی URL در لیست urlpatterens=[] تعریف شده، برای فراخوانی URL استفاده میگردد.⚠️ برای استفاده از redirect، میبایست متد آن را از کتابخانه django.shortcuts وارد نمود
from django.shortcuts import render, redirect
def ProjectCreate(request):
projectForm = forms.ProjectForm()
if request.method == 'POST':
data = forms.ProjectForm(request.POST)
if data.is_valid():
data.save()
return redirect('Projects')
context = {'form': projectForm }
return render(request, 'forms.html', context)
if request.method == 'POST':
data = forms.ProjectForm(request.POST)
if data.is_valid():
...
else:
projectForm = forms.ProjectForm()
context = {'form': projectForm }
return render(request, 'forms.html', context)
⚠️ هرگاه فرم شامل آپلود فایل باشد، باید request.FILES را هم به فرم اضافه نماییم
data = ProjectForm(request.POST, request.FILES)
enctype="multipart/form-data" را در اختیار داشته باشد.<form class="" action="" method="POST" enctype="multipart/form-data">
...
</form>