آموزش آپلود و نمایش تصویر و فایل در جنگو

مقالات

سلام

در این مطلب می خوام نحوۀ آپلود یا همان بارگذاری تصاویر و فایل ها در جنگو و سپس نمایش تصویر در صفحات رو بگم…

آموزش های متنوع و متعددی در وب وجود داره که ممکنه بعضی هاش ناقص یا فقط به یک بخش پرداخته باشد.. از مقدمه پیداست که این کار پیچیدگی خاص خودش رو داره.

در این مطلب به ترتیب مراحل زیر رو دنبال می کنیم:

  • تنظمات پروژه
  • تنظیمات مدل
  • تنظیمات فرم
  • تنظیمات  ویو
  • قالب آپلود
  • تنظیمات فایل url
  • قالب نمایش

تنظیمات پروژه

خوب اول از همه فایل settings.py رو باز می کنیم و عبارات زیر رو به انتهای اون اضافه می کنیم:

MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')

با اضافه کردن مقادیر بالا در واقع داریم به جنگو می گیم که فایل ها را در مسیر media ذخیره کنه.

برای اضافه کردن فایل و تصاویر همین کار کافیه اما اگر قصد داری تصاویر رو بعدا در صفحات نمایش بدی باید عبارت ‘django.template.context_processors.media’ رو به قسمت TEMPLATES در فایل settings.py اضافه کنیم.

#...
TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [
            os.path.join(BASE_DIR, 'templates')
        ],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
                'django.template.context_processors.media', #<-- HERE
            ],
        },
    },
]
#...

تنظیمات model

برای ساخت گزینۀ آپلود، وارد کردن همین دو خط در بخش مدل کافی است.

models.py

from django.db import models

class Document(models.Model):
    document_addr = models.FileField(upload_to='documents/')
    uploaded_at = models.DateTimeField(auto_now_add=True)

عبارت upload_to  به این معناست که فایل رو در مسیر /MEDIA_ROOT/documents آپلود می کنه. اگر این قطعه کد رو مثل زیر تغییر بدیم:

document_addr = models.FileField(upload_to='documents/%Y/%m/%d/')

فایل آپلودی رو در مسیر دقیق تری (شامل سال، ماه و روز) ذخیره می کنه. یعنی /MEDIA_ROOT/documents/2016/08/01

نکتۀ مهم دیگه اینکه که در مدل بالا باید مشخص کنی که فایل آپلودی از جنس تصویره یا از نوع سایر فایل هاست. قطعه کد زیر به جنگو اجازه می ده تا هر نوع فایلی رو آپلود کنه. اگر می خوای فایل آپلودی رو به تصاویر محدود کنی کافیه، عبارت FileField رو به ImageField تغییر بدی. بقیه موارد یکسان خواهد بود.

متغیر uploaded_at برای این است که اگر کاربری، فایلی با نام یکسان را وارد کرد، به انتهای آن عبارتی را اضافه و از تصادم فایل ها با هم جلوگیری کند.

تنظیمات فرم

اگر نمی دونی که کاربرد و مکانیزم فایل form.py چیه؛ پیشنهاد می کنم اول آموزش  فصل چهار: فرم ها | Forms  رو بخونی و بعد وارد ادامۀ آموزش بشی.

form.py

from django import forms
from uploads.core.models import Document

class DocumentForm(forms.ModelForm):
    class Meta:
        model = Document
        fields = ('document_addr' )

تنظیمات ویو

خیلی خوب. تمام فایل ها به سمت سرور از طریق متد پست (و نه GET) ارسال می شوند. بنابرین request ما از نوع POST خواهد بود. در جنگو برای دسترسی به فایل های ارسالی از request.FILES استفاده می کنیم. فرقی نمی کنه که فایل ارسالی از چه نوعی (حتی تصویر) باشه…

در ادامه هم که محتویات رو در متغیر form ذخیره می کنه.

def model_form_upload(request):
    if request.method == 'POST':
        form = DocumentForm(request.POST, request.FILES)
        if form.is_valid():
            form.save()
            return redirect('home')
    else:
        form = DocumentForm()
    return render(request, 'core/model_form_upload.html', {
        'form': form
    })

نکته: طبیعتاً محتوای فایل ها در دیتابیس ذخیره نخواهد شد. پس چی میشه؟! جنگو فایل ها را روی سرور ذخیره می کنه و صرفاً محل ذخیره سازی رو در دیتابیس ذخیره می کنه. بنابراین با پاک کردن متغیرهای دیتابیس، صرفاً آدرس ها پاک می شن و برای پاک کردن اصل فایل ها باید به صورت دستی و جداگانه اقدام کنید. (مسلماً می تونید یک متد بنویسید که هم فایل ها را از دیتابیس و هم از روی سرور پاک کنه!)

قالب آپلود

و اما قالب…

model_form_upload.html

{% extends 'base.html' %}

{% block content %}
  <form method="post" enctype="multipart/form-data">
    {% csrf_token %}
    {{ form.as_p }}
    <button type="submit">Upload</button>
  </form>

  <p><a href="{% url 'home' %}">Return to home</a></p>
{% endblock %}

نکتۀ خیلی مهم استفاده از “enctype=”multipart/form-data  در تگ مربوط به فرم است.

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

از اینجا به بعد می خواهیم ببینیم چطور می شود تصویری را که آپلود کردیم در برنامه نمایش دهیم.

اولین کار تنظیمات مربوط به settings.pyـه که در اول همین آموزش انجام شد.

تنظیمات url

اگر الان آدرس تصویر را حتی به صورت دستی وارد کنی با خطا مواجه میشی. علتش هم این است که جنگو نمی تونه این آدرس رو در قالب patternهای مربوط به url پیدا کنه. برای این کار باید دو خط زیر رو بعد از urlpatterns اضافه کنیم.

from django.conf import settings
from django.conf.urls.static import static

urlpatterns = [
    # Project url patterns...
]

if settings.DEBUG:
    urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

قالب نمایش

آدرس دهی در قالب خیلی راحته. برای اینکار کافیه از تگ زیر استفاده کنیم.

{{ MEDIA_URL}}{{document.document_addr }}

این عبارت مقادیر داخل MEDIA_URL و  بخش بعدی رو به هم می چسبونه. مثلاً کد زیر تصویری که ذخیره کردیم رو نمایش می ده…

<img src="{{ MEDIA_URL}}{{document.document_addr }}">

نویسنده:تمدن

 

بدون دیدگاه

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

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

مقالات
چگونه در جنگو منوی بازشونده یا dropdown بسازیم؟ (فرم و مدل)

سلام هدف این است که می خواهیم یک لیست بازشونده با تعداد محدودی اختیار را در فرم به کاربر نمایش دهیم. شاید این راه به ذهن برسد که فیلد را از نوع متنی در نظر می گیریم و در قسمت فرانت اند صرفاً گزینه های خود را به کاربر نمایش …

هرگونه استفادۀ از این آموزش به صورت رایگان و با ارجاع به تمدن جایز است.