Django, pandas, excel: uploading files, parsing them with pandas in Django - python

I have a big command-line script for parsing data in Excel (with pandas) and I want to wrap it with Django. I've tried both uploading files thru request.FILES and pandas, but get stuck on uploading file and, for example, saving it (not necessarily but just to check the upload for now).
Haven't had any problems with other apps on Django which didn't require uploading and parsing anything external and thought that would be much easier..:)
I've also tried Redirecting, doesn't really work, the only redirect which is actually happening is action in the form tag..
Here are the code snippets:
views.py:
def uploads(request):
if request.method == 'POST':
form = DocumentForm(request.POST, request.FILES)
if form.is_valid():
excel_file = request.FILES['document']
excel_file.save()
return render(request, 'index.html')
else:
form = DocumentForm()
return render(request, 'index.html', {'form': form})
models.py
class Document(models.Model):
document = models.FileField(upload_to="files/")
forms.py:
class DocumentForm(forms.ModelForm):
class Meta:
model = Document
fields = ('document', )
index.html:
<form
action="{% url 'reports'%}"
method="post"
enctype="multipart/form-data"
>
{% csrf_token %}
<span>
Upload .xlsx file <input type="file" name="document" />
</span>
<button type="submit">
SUBMIT
</button>
</form>

I think you must save the form's content actually:
form.save()

The reason was that I had another function in views.py leading to the same url route.

Related

Unable to add data to databse from models forms django

I am trying to send data from django forms to backend sqlite3. But I am unable to do so. I am not also getting any error or warning that help me to sort it out.
Here is models.py file
from django.db import models
GENDER_CHOICES = [
('Male', 'M'),
('Female', 'F')]
class upload(models.Model):
name = models.CharField(max_length=100)
gender = models.CharField(max_length=10, choices=GENDER_CHOICES)
phone = models.CharField(max_length=50,null=True)
email= models.EmailField(max_length=50,null=True)
file=models.FileField(upload_to='uploads/')
def __str__(self):
return self.name
here is forms.py file
from django.forms import ModelForm
from .models import upload
class uploadForm(ModelForm):
class Meta:
model = upload
fields = ['name', 'gender', 'phone', 'email','file']
Here is view.py file
from django.shortcuts import render
from .forms import uploadForm
from django.shortcuts import render
def home(request):
if request.method == 'POST':
form = uploadForm()
if form.is_valid():
form=form.save()
return HttpResponseRedirect('/')
else:
form = uploadForm()
return render(request,'home.html',{'print':form})
I am unable to understand where is the issue
This is how template file look like
<form method="post">
{% csrf_token %}
{{ print.as_p }}
<input type="submit" value="Submit">
</form>
EDIT
This issue is with FileField, I removed it, and it start saving in django database. What I want is to save file in media folder and other data in database
I also added enctype="multipart/form-data" in form
I don't think your actually sending anything to the database.
Where is says form = uploadForm() you need state you want the posted data to be sent. so this needs to be form = uploadForm(request.POST) it should then work I believe. Also when saving the form, remove the form=form.save() and leave it as form.save()
Try it out and let us know?
Solution to my post
For handling files, I need to add encryption type to my form as
enctype="multipart/form-data"
Once I added that, to access the files I should use request.FILES along with request.POST
So now I have this home function in views.py file
def home(request):
if request.method == 'POST':
form = uploadForm(request.POST,request.FILES)
if form.is_valid():
form.save()
return HttpResponseRedirect('/')
else:
form = uploadForm()
return render(request,'home.html',{'print':form})
and my template form looks like
<form action="" method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ print.as_p }}
<input type="submit" value="Submit">
</form>
Credit : https://youtu.be/Rr1-UTFCuH4?t=244

Django handle photo upload

I have model whiuch has photo attachment.
class Forum_message(models.Model):
text = models.TextField()
photo = models.ImageField(upload_to= 'forum_attachments')
I have my form(I prefer writing forms in pure html so I can have full access to modifying them)
<form action="/forum_new" method="post" enctype="multipart/form-data">
{% csrf_token %}
<input id="img_msg" type="file">
<textarea name="new_msg"></textarea>
<input type="submit" value="Submit"/>
</form>
What do I write in my function
def forum_new(request): in views.py to handle file upload and save new forum message to database?
I needed something like this:
def forum_new(request):
msg = Forum_message()
msg.user = request.user
if 'image' in request.FILES:
msg.photo = request.FILES['image']
msg.text = request.GET.get('text')
msg.save()
In views.py, you can use what is propose on the django website (https://docs.djangoproject.com/en/1.11/topics/http/file-uploads/)
If the picture is not so large, you can directly handle it as follow :
def forum_new(request):
if request.method == 'POST':
form = your_form_here(request.POST, request.FILES)
if form.is_valid():
form.save()
return redirect('/bar.html/')
else:
form = your_form_here()
return render(request, 'url.html', {'form': form})
The file should be saved in your media files in the folder forum_attachments

upload a specific file form Django/Python

I just have a upload file form in my django project (I'm using 1.10). Everything is working pretty fine actually, but as people will be uploading a csv file into the server I need to limit my logic into just request the file with a specific name and format.
This is my code:
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()
# Redirect to the document list after POST
return HttpResponseRedirect(reverse('action'))
else:
messages.add_message(request, messages.ERROR,
'Something went wrong with files! Please contact the system administrator')
return render(request, 'upaction-report.html')
# Load documents for the list page
# Render list page with the documents and the form
return render(request, 'upaction-report.html', {'form': form})
forms.py
class DocumentForm(forms.Form):
docfile = forms.FileField(
label='File format should be under the following format:',
help_text='- .csv format and under the name "Action_Report"',
)
template html
<form action="{% url "list" %}" method="post" enctype="multipart/form-data">
{% csrf_token %}
<p>{{ form.non_field_errors }}</p>
<p>{{ form.docfile.label_tag }}</p>
<p> {{ form.docfile.help_text }}</p>
<p>
{{ form.docfile }}
</p>
<p><input type="submit" value="Upload File"/></p>
</form>
Any guess on how applying that limit? In case the file is not the right just to pop up a message telling to try again until it has the right format and name. Thanks for yout time, if you need more details just let me know.
You can validate filename inside DocumentForm clean method like this:
class DocumentForm(forms.Form):
docfile = forms.FileField(
label='File format should be under the following format:',
help_text='- .csv format and under the name "Action_Report"',
)
def clean(self):
docfile = self.cleaned_data.get('docfile')
if not docfile:
raise forms.ValidationError('file is required')
if not docfile.name.startswith('filename'):
raise forms.ValidationError('incorrect file name')
if not docfile.name.endswith('fileformat'):
raise forms.ValidationError('incorrect file format')
return super(DocumentForm, self).clean()

Upload file with ajax call in django

I created form upload file in django. it is working. But when i try with ajax in django file upload is not working.
My code:
models.py
class Upload(models.Model):
documents = models.FileField(upload_to=content_file_name)
user = models.ForeignKey(User)
class Meta:
app_label = 'documentapp'
forms.py:
from django import forms
class UploadForm(forms.Form):
documents = forms.FileField()
html:
<input type="file" name="documents" id="documents" class="form-control" required="required""/>
<input type="button" id="upload_file_button" required="required" value="Upload" onclick="UploadUserDocuments()"/>
ajax in same html file:
function UploadUserDocuments() {
$.ajax({
url: "/signup/upload/",
type: "POST",
data: {
documents:$('education_documents').val(),
},
success: function(response){
}
});
}
view.py
def upload(request):
context = RequestContext(request)
if request.method == 'POST':
form = UploadForm(request.POST, request.FILES)
if form.is_valid():
handle_uploaded_file(request.FILES['file'])
return HttpResponse('true')
else:
return HttpResponse('GET')
handle_uplaoded_fiel.py
def handle_uploaded_file(f):
with open('some/file/name.txt', 'wb+') as destination:
for chunk in f.chunks():
destination.write(chunk)
There are several problems with the HTML/JS.
The first line of your HTML has a double terminating quotation for the value of the required attribute.
Your UploadUserDocuments() function does the following:
$('education_documents').val()
which is attempting to match an element such as <education_documents> rather than the usual way of selecting the value of an element by its id (i.e. using the # selector).
However, it's more involved to perform a file upload using JQuery. This answer has some ideas: How can I upload files asynchronously?
It seems that you don't send csrf_token. You can skip it for you view(which is not really recommended) by using csrf_exempt decorator.
Otherwise you should add {%csrf_token%} tag to your template. It will create hidden field with CSRF token. The way how to handle it in AJAX you can find in official documentation.
Also I'm curious why don't you render form from variable, but add HTML manually instead - but it isn't directly related to the topic.
So I'd to do it like:
html:
<form id="upload_doc" action="/signup/upload/" method="post" enctype="multipart/form-data"> {% csrf_token %}
{{form}}
<input type="submit" value="send">
</form>
Also please see notices from #Ben Rowland answer

Django import csv HTML

hi im currently try to import a csv file into a django project with out using the django admin. the code ive written seems to work when in python run but im unsure about how to build the html template as i cant seem to find any examples. Is anyone able to either post an example or point me in the right direction
my code is
Forms
class DataInput(forms.Form):
file = forms.FileField()
def save(self):
records = csv.reader(self.cleaned_data["file"])
for line in records:
parts = Part()
parts.supplier_id = line[0]
parts.name = line[1]
parts.description = line[2]
parts.save()
view
def csv_import(request):
if request.method == "POST":
form = DataInput(request.POST, request.FILES)
if form.is_valid():
form.save()
success = True
context = {"form": form, "success": success}
return render_to_response("imported.html", context,
context_instance=RequestContext(request))
else:
form = DataInput()
context = {"form": form}
return render_to_response("imported.html", context,
context_instance=RequestContext(request))
thanks in advance
Your upload template will look something like this if you just want to use the default form rendering:
<!DOCTYPE html>
<html>
...
<form enctype="multipart/form-data" method="post" action=".">
{{ form }}
</form>
...
</html>
The distinguishing part is the enctype="multipart/form-data" that lets it handle the file upload field.

Categories