Upload file with Django Views - python

I am working on a feature for a Django application that uploads files (images in my context) to the server. Everything is working fine but I am wondering how I can receive as callback the uploaded file path.
Here is my View:
def post(self, request):
if request.method == 'POST':
form = UploadFileForm(request.POST, request.FILES)
if form.is_valid():
handle_uploaded_file(request.FILES['uploadedFile'])
return redirect('/')
else:
form = UploadFileForm()
return render_to_response('index.html', {'form': form})
My Form:
class UploadFileForm(forms.Form):
uploadedFile = forms.FileField()
And my handler:
def handle_uploaded_file(source):
fd, filepath = tempfile.mkstemp(prefix=source.name, dir=FILE_UPLOAD_DIR)
with open(filepath, 'wb') as dest:
shutil.copyfileobj(source, dest)
return filepath
I know that handle_uploaded_file(request.FILES['uploadedFile']) from my view is the required string that I need as callback but how to receive it in the response?
It is possible to receive instead of my index.html (it is there just for testing purposes) the path of the image for further manipulation in the frontend part.
I might sound like a noob but I really want if that works somehow.
Also is there a way for my View to handle multiple file upload? It is something that I need to change in my handler?
Sorry for putting so many questions...

Try this:
file_path = handle_uploaded_file(request.FILES['uploadedFile'])
return render_to_response('index.html', {'form': form, 'file_path': file_path})

Related

How can I return a redirect and file in Django?

I'm working on a form that when submitted has the option to export a PDF. This is great, but I would also like to be able to return a new URL for the user to be redirected to as well as downloading the file. Something that combines render() or redirect() with FileResponse().
For this to work, you will need two views. One to serve the redirect and another one to serve the file to be downloaded. Here is a simplified implementation:
def myform(request):
form = MyForm(request.POST)
if form.is_valid():
return redirect("/download/file.pdf")
def download(request):
file = open("file.pdf", "rb")
return FileResponse(file, as_attachment=True)

How to call function if http request is POST in Django views and pass new submitted file name to function call?

I'm working on web application in which user upload a video and we perform speech recognition on it and then translate its text in another language.So, if the request is POST then we call that function which perform these functionalities and if request is GET it should not call that but in my case,on POST request, function execute first and then POST request is submitted.And it perform functionality on the last video in database.
It gives the same result even if I put function call at the end of POST request condition statement and if I put function call out of POST request condition the function call on every reload of page which is not required and I don't know other ways how to solve this problem.
"""Django==2.0.2 views.py"""
def generatingsubtitle(request):
latestvideo = Video.objects.last()
videofile = latestvideo.videofile
path = settings.MEDIA_ROOT + videofile.name
filename = os.path.splitext(videofile.name)[0]
srtpath=settings.STATIC_ROOT+filename
if request.method == 'POST':
#function call
main(path, srtpath)
form = forms.VideoForm(request.POST or None, request.FILES or None)
if form.is_valid():
form.save()
return HttpResponseRedirect(reverse('generatingsubtitle'),
)
else:
form = VideoForm()
return render(request, 'app/generate.html', {
'form': form,
'videofile': videofile,
'filename':filename,
},
)
I expect that ,POST request is submitted first and we take path of newly submitted file and pass it to the function call but the actual output is, first call the function after executing function POST request is submitted.
Any help will be highly appreciated.
You should be only be doing your processing when the form is valid and the model is saved. The way you have it, you're fetching the last model before the form is even saved, meaning you're acting on the previous model, not the current one.
Move your subtitle function inside the form.is_valid() check, then get the path to the saved file from the saved model and feed that to your processing function.
def generatingsubtitle(request):
if request.method == 'POST':
form = forms.VideoForm(request.POST or None, request.FILES or None)
if form.is_valid():
# first save the model
video_model = form.save()
# get the path of the saved file from the model
video_path = video_model.videofile.path
# this may not be necessary anymore?
[filename, ext] = os.path.splitext(video_model.videofile.name)
srtpath = settings.STATIC_ROOT + filename
# generate subtitles
main(video_path, srtpath)
return HttpResponseRedirect(reverse('generatingsubtitle'))
You should not querying the database unless the method is 'POST'. Try this.
def generatingsubtitle(request):
filename = os.path.splitext(videofile.name)[0]
videofile = latestvideo.videofile
if request.method == 'POST':
form = forms.VideoForm(request.POST or None, request.FILES or None)
if form.is_valid():
form.save()
latestvideo = Video.objects.last()
path = settings.MEDIA_ROOT + videofile.name
srtpath=settings.STATIC_ROOT+filename
#function call
main(path, srtpath)
return HttpResponseRedirect(reverse('generatingsubtitle'))
else:
form = VideoForm() #edit
context = {
'form': form,
'videofile': videofile,
'filename':filename,
}
return render(request, 'app/generate.html', context)

Django - difficulty in image upload using forms

I want to upload an image from django forms and process it using OpenCV. Here is the code I've written with the help of Django documentation:
1.forms.py:
class UploadFileForm(forms.Form):
image = forms.ImageField()
2.views.py:
def upload_file(request):
context = {'status':'not working'}
if request.method == 'POST':
form = UploadFileForm(request.POST, request.FILES)
if form.is_valid():
context['status'] = 'working'
process(request.FILES['test_01.png'])
return render(request,'create.html',context)
else:
form = UploadFileForm()
return render(request, 'create.html', {'form': form})
Here process() is the function which processes the uploaded image.Running this code gives me MultiValueDictKey Error on the line where I call process()
After searching for the error, referring to this SO answer I changed process(request.FILES['test_01.png']) to process(request.FILES.get('test_01.png')) I get Attribute Error on the same line(which I guess is because I'm not able to retrieve the uploaded image properly)
Where am I going wrong and what is the correct way of doing so?

Django validator not triggering on file upload

I have wrote a Django app for the user to upload files and see a list of uploaded files. I want to restrict the uploads to only using gif format and wrote a simple validator. Then I pass that validator in the Model, however it never triggers and the file is saved regardless of the format. Here's what I got so far.
views.py
def list(request):
# Handle file upload
if request.method == 'POST':
form = DocumentForm(request.POST, request.FILES)
if form.is_valid():
newdoc = Document(docfile=request.FILES['docfile'])
newdoc.save()
messages.add_message(request, messages.INFO, "Saved")
# Redirect to the document list after POST
return HttpResponseRedirect(reverse('list'))
else:
form = DocumentForm() # A empty, unbound form
# Load documents for the list page
documents = Document.objects.all()
# Render list page with the documents and the form
return render(
request,
'list.html',
{'documents': documents, 'form': form}
)
checkformat.py
def validate_file_type(upload):
if not (upload.name[-4:] == '.gif'):
raise ValidationError('File type not supported.')
models.py
from .checkformat import validate_file_type
def content_file_name(instance, filename):
return '/'.join(['documents', str(filename), filename])
class Document(models.Model):
docfile = models.FileField(upload_to=content_file_name, validators=[validate_file_type], null=False, verbose_name="File")
forms.py
class DocumentForm(forms.Form):
docfile = forms.FileField(
label='Select a file', widget=forms.FileInput(attrs={'accept':'image/gif'})
)
Is there something I'm missing? I've just started learning Django. Also, I know this is not a sercure way to check for a file type, but I just want to see it work to continue. Thank you for your time.
if form.is_valid():
newdoc = Document(docfile=request.FILES['docfile'])
if not '.gif' in newdoc.name:
raise ValidationError('File type not supported.')
else:
newdoc.save()
messages.add_message(request, messages.INFO, "Saved")
try this simple solution, hope it works as you need
Looks right so far. Maybe it's simply a lower/upper case issue?
A more accurate solution might be:
import os
def validate_file_type(upload):
if os.path.splitext(upload.name)[1].lower() != '.gif':
raise ValidationError('File type not supported.')
If it's still not working try to add a break point within the validation method and check the value of upload.name.
I think the problem is the form is derived from a simple Model class, but in your case you must use ModelForm instead.
This way the form knows about the Document model, and you can do some fancy operations, like calling the save mehond in the Form object so save the model instance. Also the is_valid method calls all the validations defined in the model, in addition to the validations defined in the Form itself.

forms.FilePathField doesn't work

I'm very new to django and python. I'm trying to display the list of files in a folder on my system using FilePathField like this below but for some reason, no files are displayed. I tried in many different ways but nothing worked. All I need is to get the name of the file selected. Can somebody please help me?
forms.py
class PostForm(forms.Form):
content = forms.CharField(max_length=256)
created_at = forms.DateTimeField()
file = forms.FilePathField(path='C:\input')
Here is my views.py
def post_form_upload(request):
if request.method == 'GET':
form = PostForm()
else:
# A POST request: Handle Form Upload
form = PostForm(request.POST, request.FILES)
return render(request, 'polls/post_form_upload.html', {
'form': form,
})

Categories

Resources