آموزش پایتون

آموزش ساخت فرم الکترونیکی (با آپلود فایل) و Model معادل آن و ذخیره در دیتابیس در جنگو

مراحل ساخت فرم الکترونیکی در جنگو

  1. ایجاد Model معادل جدول دیتابیس
  2. ایجاد فایل html حاوی فرم در tepmlates
  3. ایجاد فانکشن جهت مدیریت درخواستها به صفحه html مرحله قبل

۱-ایجاد Model معادل جدول دیتابیس

در ابتدا فرض می کنیم شما یک اپ برای مدیریت این نوع فرم در نظر گرفتید. و از مرحله اولیه ساخت اپ جدید در جنگو صرف نظر می کنیم.

مثلا فرض می کنیم که ما یک اپ به اسم products داریم که وظیفه مدیریت محصولات سایت رو داره. و فرم ایجاد محصول جدید رو میخوایم در همین اپ بسازیم.

به فایل models.py در اپ خودمون میریم و یک مدل برای جدول فرم میسازیم. در این مثال ما یک مدل برای محصولات ساختیم که البته کل محصولات ما از طریق همین مدل ایجاد میشن و این مدل فقط مختص فرم نیست.

اما اگر فرم شما از نوع فرم های ورود اطلاعات باشه، باید برای هر فرم یبک مدل جدید ایجاد کنید. البته کلیت کار به همون شکل انجام میشه و فقط نیتش فرق می کنه!

from django.db import models
from django.contrib.auth.models import User

class Product(models.Model):
    title = models.CharField(max_length=255)
    url = models.TextField()
    pub_date = models.DateTimeField()
    votes_total = models.IntegerField(default = 1)
    image = models.ImageField(upload_to='images/')
    icon = models.ImageField(upload_to='images/')
    body = models.TextField()
    hunter = models.ForeignKey(User, on_delete= models.CASCADE)

ما در مدل فوق، چون میخواستیم کاربر جاری رو بعنوان معرفی کننده محصول در دیتابیس درج کنیم، User رو هم ایمپورت کردیم که به صورت یک foreignKey ازش استفاده کنیم و کاربر ایجاد کننده فرم رو در دیتابیس ثبت کنیم.

البته خیلی جاها انجام این کار منطقی هست. مثلا در فرم های تماس با ما یا فرم درخواست پشتیبانی و غیره هم باید کاربری که فرم رو پر کرده در دیتابیس ثبت بشه.

فیلد آخری که ما با نام hunter ساختیم (و البته میشد با نام user بسازیمش) کاربر ارسال کننده فرم رو در دیتابیس ذخیره می کنه.

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

علاوه بر اینها، ما دوتا فیلد image و icon رو هم در مدل خودمون داریم که برای پر شدن اونها باید آپلود انجام بشه.

۲- ایجاد فایل html حاوی فرم در tepmlates

در حالی که یادتون هست و فولدر templates رو به فایل settings.py معرفی کردین،‌ یک صفحه برای فرم مربوطه در این فولدر ایجاد کنید.

ما این صفحه رو با نام create.html ساختیم. شما با اسم دلخواه خودتون بسازید.

در این صفحه یک فرم الکترونیکی ایجاد می کنیم و {% csrf_token %} رو داخل فرم قرار میدیم. جنگو بدون این توکن، فرم ارسالی رو تراست نمی کنه و بهتون ارور میده.

متد ارسالی فرم رو روی POST تنظیم کرده و آدرس Action رو روی صفحه جاری قرار میدیم.

 <form method="post" action="{% url 'create' %}" enctype="multipart/form-data">
    {% csrf_token %}
    Title:
    <br>
    <input type="text" name="title" class="form-control" required/>
    URL:
    <br>
    <input type="text" name="url" class="form-control" required/>
    Body:
    <br>
    <textarea name="body" id="" cols="70" rows="10" class="form-control" required>

    </textarea>
    Icon(Thumbnail):
    <input type="file" name="icon" class="form-control" required/>
    Image:
    <input type="file" name="image" class="form-control" required/>
    <br>
    <input class="btn btn-primary" type="submit" value="Add Product" class="form-control"/>

</form>

دقت کنید چون فرم ما آپلود فایل هم دارد باید اتریبیوت enctype=”multipart/form-data” رو هم براش بنویسیم.

۳- ایجاد فانکشن جهت مدیریت درخواستها به صفحه html مرحله قبل

در فایل views.py یک فانکشن جدید برای مدیریت درخواستهای ارسالی به این صفحه ایجاد می کنیم.

# فانکشنی که این انوتیشن را دارد فقط زمانی اجرا میشود که کاربر لاگین کرده باشد. و در غیر اینصورت خطا بر می گرداند
@login_required
def create(request):
    # چک میکنه اگه رکوئست از نوع POST باشه فرم ارسالی رو پردازش کنه. در غیر اینصورت صفحه فرم رو به کاربر نشون بده
    if request.method == 'POST':
        # چک میکنه که تمام فیلدهای الزامی پر شده باشه
        if request.POST['title'] and request.POST['url'] and request.POST['body'] and request.FILES['icon'] and request.FILES['image']:
            # یک نمونه از کلاس پروداکت ایجاد میکنه
            product = Product() # means :=>  Product product = new Product(); in Java and C#
            # فیلد عنوان نمونه ایجاد شده ازکلاس رو با دیتای فیلد عنوان فرم ارسالی پر میکنه
            product.title = request.POST['title']
            # چک میکنه اگر فیلد url اولش http یا https خورده باشه اون رو داخل فیلد مربوطه ذخیره کنه
            if request.POST['url'].startswith('http://') or request.POST['url'].startswith('https://'):
                product.url = request.POST['url']
            # در غیر اینصورت به اول url یک http:// اضافه می کنه و اون رو داخل فیلد مربوطه میریزه
            else:
                product.url = ('http://' + request.POST['url'])
            product.body = request.POST['body']
            # دقت کنید برای گرفتن فایلهای آپلود شده ی فرم، بجای request.POST از request.FILES استفاده می کنیم
            product.icon = request.FILES['icon']
            product.image = request.FILES['image']
            product.pub_date = timezone.datetime.now()
            # در اینجا یوزری که این ریکوئست را ایجاد کرده راداخل فیلد هانتر - که به معنی کاربر ایجاد کننده پروداکت هست - میریزه
            product.hunter = request.user
            # در نهایت باید نمونه ایجاد شده از کلاس پروداکت رو که با دیتای ورودی کاربر پر ش کردیم، در دیتابیس ذخیره می کنیم.
            # دقت کنید اگر این رو ذخیره نکنید انگار تا اینجا اصلا هیچ کاری انجام ندادید و چیزی در دیتابیس ذخیره نمیشه
            product.save()
            # بعد از اینکه پروداکت جدید ایجاد شد، لینک زیر با استفاده از ID پروداکت ایجاد می شود و کاربر به صفحه این پروداکت ریدایرکت میشود
            return redirect('/products/' + str(product.id))
# چک میکنه اگر متد رکوئست GET باشه، کاربر رو به صفحه فرم منتقل میکنه 
    else:
        return render(request, 'products/create.html')

ما میخواستیم فرم ما رو فقط کاربر لاگین بتونه پر کنه. به همین دلیل login_required رو ایمپورت کردیم و انوتیشن @login_required رو بالای متد نوشتیم . این انوتیشن باعث میشه فقط کاربر لاگین کرده بتونه این درخواست رو ارسال کنه. در غیر اینصورت بهش ارور بر می گردونه.

البته میتونیم به @login_required یک آدرس هم بعنوان ریدایرکت بدیم، که در صورتی که کاربرلاگین نبود، اون رو به صفحه مورد نظر ریدایرکت کنه. این مورد رو در آموزش مربوط به نمایش محتوا فقط به کاربر ثبت نام کرده به صورت کامل براتون توضیح دادم.

اگر کاربر صفحه create.html رو به صورت دستی یا به صورت لینک وارد کرده باشه (که در اون صورت متد درخواستش GET هست) باید صفحه html به کاربر نمایش داده بشه.

ولی اگر کاربر فرم رو سابمیت کنه – چون متد ارسال فرم رو روی POST گذاشته بودیم – درخواست با متد POST ارسال میشه.

به همین دلیل ما با یک دستور شرطی مشخص کردیم که وقتی درخواست از نوع GET بود، صفحه فرم رو به کاربر نمایش بده، ولی وقتی درخواست از نوع POST بود، فرم رو پردازش کنه.

از models ، کلاس Product رو ایمپورت می کنیم که بتونیم یک نمونه ازش ایجاد کنیم.

هر کدام از فیلدها رو با مقادیری که از طریق فرم ارسال شده (بوسیله متد request.POST) مقداردهی می کنیم.

توجه کنید فیلد های فایل رو باید با متد request.FILES دریافت کنیم.

و در نهایت با دستور product.save رکورد مربوطه رو داخل دیتابیس ذخیره می کنیم.

حامد عسکریان

برنامه نویس و عاشق تکنولوژی

دیدگاهتان را بنویسید

دکمه بازگشت به بالا
بستن
بستن