I'm trying to upload a csv file in my view. I included csrf token however I'm directly taking 403 error when I try to upload a file. Here is my view and template:
MY FORM HTML
<div class="file-boxes">
<form enctype="multipart/form-data" action="" encoding="multipart/form-data" id="upload-csv" method="post">
{% csrf_token %}
{{form.csv}}
<!-- <input class="input-file" id="fileInput" type="file" size="14" name="csv_upload" onchange="this.form.submit()"> -->
</form>
</div>
MY FORM
class DeliveryDataForm(forms.Form):
csv = forms.FileField(widget=forms.ClearableFileInput(attrs={'size:':14,'onchange':'this.form.submit()'}))
MY VIEW
def upload_data(request):
...
form = DeliveryDataForm()
if request.method == "POST":
import pdb
pdb.stack_trace()
form = DeliveryDataForm(request.POST, request.FILES)
return HttpResponse('asd')
return render_to_response(template,context)
I know there are some missing parts in the view but the strange thing is, it never enters the if part. Any idea ?
from django.shortcuts import render
# ...
# return render_to_response(template,context)
return render(request,'index.html',context)
Related
I searched all around the web and didn't find an answer so hopefully this is not a duplicate. So I am trying to build a browser app using Django and are using some Jinja code in my html file, but the html file when loaded into a browser doesn't recognize Jinja code and only display raw code. In fact after some experimentation I found out that my browser doesn't display correctly any Jinja code. I checked and I've installed Jinja2 on my computer.
My html file looks like this:
<!DOCTYPE html>
<html>
<head>
<title>Music FFT Visualizer</title>
<style></style>
</head>
{% block content %}
<body>
<form method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Upload a Song</button>
</form>
</body>
{% endblock %}
<html>
and my view.py looks like this:
from django.shortcuts import render
from .forms import MusicVisualizerForm
from .models import MusicVisualizer
def lastSong(request):
MusicVisualizers = MusicVisualizer.objects.all()
MusicVisualizer_last = MusicVisualizers[len(MusicVisualizers)-1]
return render(request, 'MusicVisualizer/templates/MusicVisualizer.html', { 'MusicVisualizer' : MusicVisualizer_last})
def uploadSong(request):
if request.method == 'POST':
form = MusicVisualizerForm(request.POST, request.FILES)
if form.is_valid():
form.save()
else:
form = MusicVisualizerForm()
return render(request, 'MusicVisualizer/templates/MusicVisualizer.html', {'form' : form})
my webpage looks like this:
I have two forms on the same page.
The first form uses a 3rd party lib to upload a file to s3 and then preview what it just uploaded without changing state/ going to a different page.
The second form is going to save the url of the uploaded file to my model
However, when I submit the second form - the first form throws an error. About not having the required field (it thinks it is supposed to submit another file).
HTML
<form
id="s3form"
name="s3form"
action="{% url 'file_create' employee.uid %}"
method="post"
>
{% csrf_token %}
{{ form }}
</form>
<hr/>
<form
id="save-pic"
name="save-pic"
action="{% url 'employee_update_profile_pic' employee.uid %}"
method="post"
>
{% csrf_token %}
{# jquery inserts hidden input for image link after s3 upload #}
<input
id="save-pic-submit"
name="save-pic-submit"
type="submit"
value="Save"
>
</form>
UPDATE:
urls.py
path('employee/update/<str:uid>/profile-picture', views.file_create, name='file_create'),
path('employee/update/<str:uid>/profile-picture', views.employee_update_profile_pic, name='employee_update_profile_pic'),
views.py
def file_create(request, uid):
employee = Employee.nodes.get(uid=uid)
form = S3UploadForm(request.POST or None)
# this is not getting run... maybe because form intercepted by package?
if form.is_valid():
form.save()
messages.success(request, '''Successfully uploaded new profile pic! Lookin' good''')
return redirect("employee_detail", employee.uid)
return render(request, 'profile-picture.html', {'form': form, 'employee': employee})
def employee_update_profile_pic (request):
pdb.set_trace()
SOLVED: it was because they were sharing the same URL despite both being 'post'
I am currently learning Django. I am building a system that gets input from the user as image and throws back the damage level. I have the python files all caught up. But I am having difficulty doing the Django part.
How do I get an image as input from the user ?
And how will I throw back the result of the code that does the damage level prediction to the front end ?
Thanks in advance
To get images from user you can do as following. However getting data from request is not recommended way.
Views.py
from django.shortcuts import render, render_to_response
from django.core.files.storage import FileSystemStorage
def index(request):
if request.POST:
if request.method == 'POST' and request.FILES['image']:
uploaded_image = request.FILES['image']
fs = FileSystemStorage()
filename = fs.save(uploaded_image.name, uploaded_image)
uploaded_file_url = fs.url(filename)
code = get_code(uploaded_file_url)
return render_to_response("homepage.html", {"code": code})
else:
return render(request, "homepage.html")
Using this request.FILES['image'] we are getting a image from our form passed on post event.
In your template homepage.html
<form method="post" action="{% url 'code' %}" enctype="multipart/form-data">
{% csrf_token %}
<input type="file" name="image" id="file-input" accept="image/x-png,image/jpeg,image/jpg"/>
<input type="submit" style="background: #0b0b0b" class="btn btn-secondary" value="Generate Caption"/>
<br><br>
<div style="background: #0b0b0b">
<a>Code for image is : {{ code }}</a>
</div>
</form>
{% url 'code' %} this will reverse the url by name as defined in urls.py. {% csrf_token %} is required for security reasons. enctype="multipart/form-data" is required to pass data like images, files etc. Input with name name="image" is what we are looking in request.FILES['image']. If you want change the name make your to change it everywhere.
And in your urls.py
from django.conf.urls import url
urlpatterns = [
url(r'^$', views.homepage, name='code'),
]
Also you can have look at Django forms for a better way.
I have already consulted lots of forums and I can't get an answer. I have installed a file upload in my Django app to save data into my server. But it does not work. Instead, it raises a MultiValueDictKeyError. I guess the problem is that there is not request.FILES (because it raises an error in request.FILES mentions), so the file upload is not working. This is my views.py:
def list_files(request, phase_id):
phase = get_object_or_404(Phase, pk=int(phase_id))
if request.method == 'POST':
#form = DocumentForm(request.POST, request.FILES)
form = DocumentForm(request.POST, request.FILES)
if form.is_valid():
newdoc = Document(docfile = request.FILES['docfile'], phase = phase_id)
newdoc.save()
doc_to_save = request.FILES['docfile']
filename = doc_to_save._get_name()
fd = open(settings.MEDIA_URL+'documents/'+str(filename),'wb')
for chunk in doc_to_save.chunks():
fd.write(chunk)
fd.close()
return HttpResponseRedirect(reverse('list_files'))
else:
form = DocumentForm()
documents = Document.objects.filter(phase=phase_id)
return render_to_response('teams_test/list_files.html',{'documents': documents, 'form':form, 'phase':phase}, context_instance = RequestContext(request)
)
The document form in forms.py:
class DocumentForm(forms.ModelForm):
docfile = forms.FileField(label='Select a file', help_text='max. 42 megabytes')
class Meta:
model = Document
The class document in models.py:
class Document(models.Model):
docfile = models.FileField(upload_to='documents')
phase = models.ForeignKey(Phase)
Finally, my html code:
{% extends "layouts/app.html" %}
{% load i18n user %}
{% block title %}{% trans "Files list" %}{% endblock %}
{% block robots %}noindex,nofollow{% endblock %}
{% block page%}
<div id="page" class="container">
<div class="header prepend-2 span-20 append-2 last whiteboard">
<h2 style="margin-left:-40px">{{ phase.name }} files</h2>
{% if documents %}
<ul>
{% for document in documents %}
<li><a href="{{ document.docfile.url }}">{{ document.docfile.name }}
{% endfor %}
</ul>
{% else %}
<p>No documents.</p>
{% endif %}
<form action="{% url list_files phase.id %}" method="post" enctype="multipart/form-data">
{% csrf_token %}
<input id="file" type="file" />
<input id="submit" type="submit" value="Upload file" />
</form>
</div>
</div>
{% endblock %}
My traceback says:
Exception Type: MultiValueDictKeyError
Exception Value: "Key 'docfile' not found in <MultiValueDict: {}>"
my_dir/views.py in list_files
newdoc = Document(docfile = request.FILES['docfile'], phase = phase_id)
And my QueryDict is empty:
POST:<QueryDict: {u'csrfmiddlewaretoken': [u'UZSwiLaJ78PqSjwSlh3srGReICzTEWY1']}>
Why? What am I doing wrong?
Thanks in advance.
You need to change multipart/form_data to multipart/form-data - that's why request.FILES is empty: the form isn't sending things in the way Django expects due to the typo. [EDIT: this has now been done]
Update 1: Also, rather than directly access request.FILES, try relying on the modelform's default behaviour, as then it'll have been handled as an upload appropriately. ie, newdoc = form.save() should do all you need, from a quick look at it - is there a particular reason you manually saving the file when the modelform can do that for you?
Update 2: Ah, look: you're not assigning a name to your file upload element
From the docs:
HttpRequest.FILES A dictionary-like object containing all uploaded files. Each key in FILES is the name from the <input type="file" name="" />. Each value in FILES is an UploadedFile
So, you need to change
<input id="file" type="file" />
to
or, for default Django convention
<input id="id_docfile" type="file" name="docfile"/>
Indeed, it's usually better to use the Django form to render the actual field, even if you've moved beyond the whole {{form.as_p}} approach:
{{form.docfile}}
PS. if you've not read them fully, I heartily recommend taking the time to go through all of the forms documentation
Modify Post method to
<form action="" method="post" enctype="multipart/form-data">{% csrf_token %}
For anymore who tried the above and still couldn't figure out a solution. Here's what I did:
views.py
if request.method == 'POST':
doc = request.FILES #returns a dict-like object
doc_name = doc['filename']
...
For anyone who tried the above and still couldn't figure out a solution. Here's what I did (2nd part):
if request.method == 'POST' and 'filename' in request.FILES:
doc = request.FILES #returns a dict-like object
doc_name = doc['filename']
...
I want to upload the image to the server. for that I have created a form and within my views.py file I tried to submit it into the sever. Here it does not uploads the file to "images" folder. instead of that it only update the database filed with new image name. So can anyone give me a solution.
this is views.py file
#login_required
def edit_profile(request):
if request.POST:
employee = Employee.objects.get(user=request.user)
employee.avatar=request.POST.get('image')
employee.save()
return HttpResponseRedirect('/view_profile/')
user_profile = request.user.get_profile()
return render_to_response('edit_profile.html',{'profile':user_profile },context_instance=RequestContext(request))
here my html code
{% block content %}
<form action="." method="post">
{% csrf_token %}
<input type="file" name="image"/>
<input type="submit" value="Save Changes" name="save" />
</form>
{% endblock %}
what should i change to upload image to the "images" folder
You need to add enctype="multipart/form-data" in your form element, so that files are also uploaded and available in request.FILES in the view..
So update it to
<form action="." method="post" enctype="multipart/form-data" >
....
More info at Binding uploaded files to a form
To save the image its easier to use ModelForm and set image file appropriately. But still you want to save the object directly do
...
employee.avatar = request.FILES['image']
employee.save()
Ref File Uploads