Django 2.1 - File Uploads

फ़ाइल अपलोड




django

फ़ाइल अपलोड

जब Django एक फ़ाइल अपलोड को संभालता है, तो फ़ाइल डेटा request.FILES में रखा जाता है। request.FILES ( request ऑब्जेक्ट पर अधिक अनुरोध और प्रतिक्रिया ऑब्जेक्ट के लिए दस्तावेज़ देखें)। यह दस्तावेज़ बताता है कि डिस्क और मेमोरी में फ़ाइलों को कैसे संग्रहीत किया जाता है, और डिफ़ॉल्ट व्यवहार को कैसे अनुकूलित किया जाए।

चेतावनी

यदि आप अविश्वसनीय उपयोगकर्ताओं से अपलोड की गई सामग्री स्वीकार कर रहे हैं तो सुरक्षा जोखिम हैं! शमन विवरण के लिए उपयोगकर्ता द्वारा अपलोड की गई सामग्री पर सुरक्षा गाइड के विषय को देखें।

बेसिक फ़ाइल अपलोड

FileField वाले एक सरल फॉर्म पर विचार करें:

from django import forms

class UploadFileForm(forms.Form):
    title = forms.CharField(max_length=50)
    file = forms.FileField()

इस फ़ॉर्म को संभालने वाले दृश्य को request.FILES में फ़ाइल डेटा प्राप्त होगा। FileField , जो एक शब्दकोश है जिसमें FileField प्रत्येक FileField (या ImageField , या अन्य FileField उपवर्ग) की FileField । तो उपरोक्त फॉर्म का डेटा request.FILES['file'] रूप में सुलभ होगा। request.FILES['file']

ध्यान दें कि request.FILES में केवल तभी डेटा होगा जब अनुरोध विधि POST और <form> जिसने अनुरोध पोस्ट किया है, में विशेषता enctype="multipart/form-data" । अन्यथा, request.FILES खाली हो जाएगा।

अधिकांश समय, आप फ़ाइल डेटा को request से फ़ॉर्म में बाइंडिंग फ़ाइलों में बताए गए फ़ॉर्म से पास करेंगे। यह कुछ इस तरह दिखेगा:

from django.http import HttpResponseRedirect
from django.shortcuts import render
from .forms import UploadFileForm

# Imaginary function to handle an uploaded file.
from somewhere import handle_uploaded_file

def upload_file(request):
    if request.method == 'POST':
        form = UploadFileForm(request.POST, request.FILES)
        if form.is_valid():
            handle_uploaded_file(request.FILES['file'])
            return HttpResponseRedirect('/success/url/')
    else:
        form = UploadFileForm()
    return render(request, 'upload.html', {'form': form})

ध्यान दें कि हमें request.FILES पास करना है। फॉर्म के कंस्ट्रक्टर में शामिल हों; इस प्रकार फ़ाइल डेटा एक फ़ॉर्म में बंध जाता है।

यहां एक सामान्य तरीका है जो आप अपलोड की गई फ़ाइल को संभाल सकते हैं:

def handle_uploaded_file(f):
    with open('some/file/name.txt', 'wb+') as destination:
        for chunk in f.chunks():
            destination.write(chunk)

UploadedFile.chunks() पर लूपिंग का उपयोग read() बजाय read() सुनिश्चित करता है कि बड़ी फ़ाइलें आपके सिस्टम की मेमोरी को अभिभूत नहीं करती हैं।

UploadedFile ऑब्जेक्ट पर कुछ अन्य विधियाँ और विशेषताएँ उपलब्ध हैं; संपूर्ण संदर्भ के लिए UploadedFile देखें।

एक मॉडल के साथ अपलोड की गई फ़ाइलों को संभालना

यदि आप किसी फ़ाइल को किसी FileField Model पर सहेज रहे हैं, तो एक FileField का उपयोग करके इस प्रक्रिया को बहुत आसान बना दिया जाता है। फ़ाइल ऑब्जेक्ट को कॉल करने के स्थान पर FileField जब form.save() कॉल किया form.save() तो संबंधित FileField के upload_to तर्क द्वारा निर्दिष्ट किया जाता है:

from django.http import HttpResponseRedirect
from django.shortcuts import render
from .forms import ModelFormWithFileField

def upload_file(request):
    if request.method == 'POST':
        form = ModelFormWithFileField(request.POST, request.FILES)
        if form.is_valid():
            # file is saved
            form.save()
            return HttpResponseRedirect('/success/url/')
    else:
        form = ModelFormWithFileField()
    return render(request, 'upload.html', {'form': form})

यदि आप मैन्युअल रूप से किसी ऑब्जेक्ट का निर्माण कर रहे हैं, तो आप फ़ाइल ऑब्जेक्ट को request.FILES से असाइन कर सकते हैं। मॉडल में फ़ाइल फ़ील्ड पर फ़ाइल:

from django.http import HttpResponseRedirect
from django.shortcuts import render
from .forms import UploadFileForm
from .models import ModelWithFileField

def upload_file(request):
    if request.method == 'POST':
        form = UploadFileForm(request.POST, request.FILES)
        if form.is_valid():
            instance = ModelWithFileField(file_field=request.FILES['file'])
            instance.save()
            return HttpResponseRedirect('/success/url/')
    else:
        form = UploadFileForm()
    return render(request, 'upload.html', {'form': form})

कई फाइलें अपलोड की जा रही हैं

यदि आप एक प्रपत्र फ़ील्ड का उपयोग करके कई फ़ाइलों को अपलोड करना चाहते हैं, तो फ़ील्ड के विजेट की multiple HTML विशेषता सेट करें:

from django import forms

class FileFieldForm(forms.Form):
    file_field = forms.FileField(widget=forms.ClearableFileInput(attrs={'multiple': True}))

फिर कई फ़ाइल अपलोड को संभालने के लिए अपने FormView उपवर्ग की post विधि को ओवरराइड करें:

from django.views.generic.edit import FormView
from .forms import FileFieldForm

class FileFieldView(FormView):
    form_class = FileFieldForm
    template_name = 'upload.html'  # Replace with your template.
    success_url = '...'  # Replace with your URL or reverse().

    def post(self, request, *args, **kwargs):
        form_class = self.get_form_class()
        form = self.get_form(form_class)
        files = request.FILES.getlist('file_field')
        if form.is_valid():
            for f in files:
                ...  # Do something with each file.
            return self.form_valid(form)
        else:
            return self.form_invalid(form)

हैंडलर्स अपलोड करें

जब कोई उपयोगकर्ता किसी फ़ाइल को अपलोड करता है, तो Django फ़ाइल डेटा को अपलोड हैंडलर के पास भेज देता है - एक छोटा वर्ग जो फ़ाइल डेटा को संभालता है जैसे ही वह अपलोड होता है। अपलोड हैंडलर को शुरू में FILE_UPLOAD_HANDLERS सेटिंग में परिभाषित किया गया है, जो FILE_UPLOAD_HANDLERS चूक करता है:

["django.core.files.uploadhandler.MemoryFileUploadHandler",
 "django.core.files.uploadhandler.TemporaryFileUploadHandler"]

साथ में MemoryFileUploadHandler और TemporaryFileUploadHandler Django की डिफॉल्ट फाइल अपलोड की गई मेमोरी को छोटे फाइल को डिस्क पर और बड़े लोगों में पढ़ने का व्यवहार प्रदान करते हैं।

आप कस्टम हैंडलर लिख सकते हैं जो अनुकूलित करता है कि कैसे Django फ़ाइलों को संभालता है। उदाहरण के लिए, आप उपयोगकर्ता-स्तरीय कोटा लागू करने के लिए कस्टम हैंडलर का उपयोग कर सकते हैं, मक्खी पर डेटा को संपीड़ित कर सकते हैं, प्रगति सलाखों को प्रस्तुत कर सकते हैं, और यहां तक ​​कि इसे स्थानीय रूप से संग्रहीत किए बिना सीधे दूसरे संग्रहण स्थान पर डेटा भेज सकते हैं। विवरण अपलोड करने के लिए कस्टम अपलोड हैंडलर देखें कि आप अपलोड व्यवहार को कैसे अनुकूलित या पूरी तरह से बदल सकते हैं।

जहां अपलोड किया गया डेटा संग्रहीत है

अपलोड की गई फ़ाइलों को सहेजने से पहले, डेटा को कहीं संग्रहीत करने की आवश्यकता है।

डिफ़ॉल्ट रूप से, यदि अपलोड की गई फ़ाइल 2.5 मेगाबाइट से छोटी है, तो Django मेमोरी में अपलोड की संपूर्ण सामग्री को रखेगा। इसका मतलब है कि फ़ाइल को सहेजने में केवल मेमोरी से रीड और डिस्क से राइट शामिल है और इस प्रकार यह बहुत तेज़ है।

हालाँकि, यदि कोई अपलोड की गई फ़ाइल बहुत बड़ी है, तो Django आपके सिस्टम की अस्थायी निर्देशिका में संग्रहीत अस्थायी फ़ाइल पर अपलोड की गई फ़ाइल लिख देगा। यूनिक्स-जैसे प्लेटफ़ॉर्म पर इसका मतलब है कि आप Django से एक फ़ाइल उत्पन्न करने की उम्मीद कर सकते हैं जिसे /tmp/tmpzfp6I6.upload जैसी /tmp/tmpzfp6I6.upload चीज़ कहा जाता है। यदि कोई अपलोड काफी बड़ा है, तो आप इस फाइल को आकार में बढ़ते हुए देख सकते हैं क्योंकि Django डिस्क पर डेटा स्ट्रीम करता है।

इन बारीकियों - 2.5 मेगाबाइट; /tmp ; आदि - बस "उचित चूक" हैं जिन्हें अगले अनुभाग में वर्णित अनुसार अनुकूलित किया जा सकता है।

अपलोड हैंडलर व्यवहार बदलना

कुछ सेटिंग्स हैं जो Django के फ़ाइल अपलोड व्यवहार को नियंत्रित करती हैं। विवरण के लिए फ़ाइल अपलोड सेटिंग्स देखें।

मक्खी पर अपलोड हैंडलर्स को संशोधित करना

कभी-कभी विशेष विचारों को अलग-अलग अपलोड व्यवहार की आवश्यकता होती है। इन मामलों में, आप request.upload_handlers को संशोधित करके प्रति-अनुरोध के आधार पर हैंडलर अपलोड कर सकते हैं। डिफ़ॉल्ट रूप से, इस सूची में FILE_UPLOAD_HANDLERS द्वारा दिए गए अपलोड हैंडलर शामिल FILE_UPLOAD_HANDLERS , लेकिन आप सूची को संशोधित कर सकते हैं जैसा कि आप किसी अन्य सूची में करेंगे।

उदाहरण के लिए, मान लें कि आपने एक ProgressBarUploadHandler लिखा है जो कुछ प्रकार के AJAX विजेट पर अपलोड प्रगति पर प्रतिक्रिया प्रदान करता है। आप इस हैंडलर को अपने अपलोड करने वाले हैंडलर से इस तरह जोड़ेंगे:

request.upload_handlers.insert(0, ProgressBarUploadHandler(request))

आप शायद इस मामले में list.insert() बजाय list.insert() का उपयोग करना चाहते हैं क्योंकि किसी अन्य हैंडलर से पहले एक प्रगति बार हैंडलर को चलाने की आवश्यकता होगी। याद रखें, अपलोड हैंडलर क्रम में संसाधित किए जाते हैं।

यदि आप अपलोड हैंडलर को पूरी तरह से बदलना चाहते हैं, तो आप एक नई सूची प्रदान कर सकते हैं:

request.upload_handlers = [ProgressBarUploadHandler(request)]

ध्यान दें

आप request.POST से पहले केवल अपलोड हैंडलर्स को संशोधित कर सकते हैं request.POST या request.FILES तक पहुँचने से पहले - अपलोड हैंडलर को बदलने से कोई मतलब नहीं है अपलोड अपलोडिंग शुरू होने के बाद। यदि आप request.POST या request.FILES से पढ़ने के बाद request.upload_handlers को संशोधित करने का प्रयास करते हैं।

इस प्रकार, आपको हमेशा अपने दृश्य में यथाशीघ्र अपलोड करने वाले हैंडलर को संशोधित करना चाहिए।

इसके अलावा, request.POST CsrfViewMiddleware द्वारा एक्सेस किया CsrfViewMiddleware जो डिफ़ॉल्ट रूप से सक्षम होता है। इसका मतलब है कि आपको अपलोड हैंडलर बदलने की अनुमति देने के लिए अपने दृष्टिकोण पर csrf_exempt() का उपयोग करने की आवश्यकता होगी। फिर आपको फ़ंक्शन पर csrf_protect() का उपयोग करना होगा जो वास्तव में अनुरोध को संसाधित करता है। ध्यान दें कि इसका मतलब है कि CSRF की जाँच होने से पहले हैंडलर फ़ाइल अपलोड प्राप्त करना शुरू कर सकते हैं। उदाहरण कोड:

from django.views.decorators.csrf import csrf_exempt, csrf_protect

@csrf_exempt
def upload_file_view(request):
    request.upload_handlers.insert(0, ProgressBarUploadHandler(request))
    return _upload_file_view(request)

@csrf_protect
def _upload_file_view(request):
    ... # Process request