Django-.csv file is not properly storing - python

views.py
def preprocessedDatafile(request):
file2 = request.FILES["myfile"]
dtf = pd.DataFrame(file2)
dtf.to_csv(
"E:/Preprocessed/preprocessed data.csv"
)
return render(request, "preprocessedDatafile.html")
In the above pd is the panadas library object.
.html
<form class="grid" method="POST" action="{% url 'preprocessedDatafile' %}" enctype="multipart/form-data">
{% csrf_token %}
<div style="border: 1px dashed rgb(148,10,34); width:59%" >
<br/><br/>
<input type="file" class='upload-box' accept=".csv" name='myfile'/>
<br/><br/><br/>
</div>
<button type="submit" id="btn" ><b>Submit</b></button>
</form>
I am making a web page, where I have to read a csv file and then store this csv file in a specific location. What I want to do is done but the new csv that I am storing have some garbage data and all data is storing in one column. I want to store new file data same as the original file data. For more understanding the picture of original file is:
and the picture of new file that is currently storing is:
I hope you understood what I am taking. Is there a way to get the same data as in the original file in the new file that I am storing.

I used the below code in the views.py file and my problem is resolved.
def preprocessedDatafile(request):
file2 = request.FILES["myfile"]
dtfb = pd.read_csv(file2)
dtf = pd.DataFrame(dtfb)
dtf.to_csv(
"E:/Preprocessed/preprocessed data.csv"
)
return render(request, "preprocessedDatafile.html")

Related

Django - How to get user file path?

I have to accept excel file from user and perform some operation on it using pandas dataframe.
So to load the dataframe using pandas I need to pass the path of file:
fd =pd.read_excel('C:\users\chan\desktop\abc.xlsx')
In django I am trying to use HTML input type file to get the location of file, so that I can pass it in pandas but unable to get file location in python variable.
I tried below code but it's printing data on html page instead of storing it's path in variable:
HTML:
<html>
<head>
<title>Coordinates to Bounding Box</title>
</head>
<body>
<form method="post" enctype="multipart/form-data">
{% csrf_token %}
<input id="uploadbutton" type="file" value="Browse" name="file" accept="text/csv" />
<input type="submit" value="Upload" />
</form>
{% block content %}
<h3>File uploaded successfully</h3>
{{file.name}}
</br>content = {{contentOfFile}}
{% endblock %}
</body>
</html>
Django's views.py
from django.shortcuts import render
from django.conf.urls.static import static
from django.http import HttpResponse
# Create your views here.
def index(request):
if request.method == 'POST':
file1 = request.FILES['file']
contentOfFile = file1.read()
if file1:
return render(request, 'index.html', {'file': file1, 'contentOfFile': contentOfFile})
return render(request,'index.html')
Is there any way I can get the path of excel file or load the excel data in pandas dataframe?
in html you put:
<input type="file" name="excel_file" accept=".xlsx">
then in views.py:
excel_file = request.FILES.get('excel_file')
df = pd.read_excel(excel_file)

Pandas dataframe not acting as expected once deployed to heroku (Django project)

I have created a program which does data entry and returns a pandas table (the info is saved in a list, called JOB_INFO, at the top of the views.py file - I will attach this below) with some results which can be downloaded. I also have the table rendering on the html page that has the data entry form - the table renders below the form and updates(appends) with each user input(form submit). This is works perfectly in development on my local machine, but when it's been successfully deployed to heroku, it starts acting up and not behaving as expected.
Examples include:
Not updating the table - the form seems to submit but the table doesn't update. If I keep trying, it suddenly works. But then I'll try another and the previous one disappears and only the latest one will show in the table. It just seems so random.
Not emptying the list - I have a button to clear the table but that doesn't work either. If I click the button a bunch of time it might work suddenly. But then randomly some information will show up in the table again that I thought was cleared!
Info in downloaded file when I thought I cleared it - this one is kind of self-explanatory.
In a nutshell, calling it random is probably the best way to describe it. It's just not doing what I want it to do and what is expected of it.
views.py
from django.shortcuts import render, redirect, get_object_or_404, reverse, HttpResponse
from django.core.exceptions import ObjectDoesNotExist, MultipleObjectsReturned
from .models import Data
from .forms import DataForm, SearchAndUpdateForm
from io import BytesIO
import pandas as pd
import xlsxwriter
JOB_INFO = {
"Plentific Job Number": [],
"WorkOrder Number": [],
"Invoice Number Found": [],
"Payments": [],
"Job Number Exists": [],
}
def data_entry(request):
"""
Creates new instance of data entry form and renders it on html page
along with a report table, which updates with each data entry input
"""
form = SearchAndUpdateForm()
df = pd.DataFrame(JOB_INFO,
columns=[
"Plentific Job Number",
"WorkOrder Number",
"Invoice Number Found",
"Payments",
"Job Number Exists",
])
if not df.empty:
df_html = df.to_html(classes="table table-striped table-hover")
return render(request, "data_entry.html", {
"form": form, "df_html": df_html})
else:
return render(request, "data_entry.html", {
"form": form})
def export_job_info_report(request):
"""
Exports the job_info list as an Excel spreadsheet
and saves it to user's local directory
"""
df = pd.DataFrame(JOB_INFO)
output = BytesIO()
writer = pd.ExcelWriter(output, engine='xlsxwriter')
df.to_excel(writer, sheet_name='report', index=False)
writer.save()
output.seek(0)
response = HttpResponse(output,
content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')
response['Content-Disposition'] = 'attachment; filename=%s.xlsx' % 'Download'
return response
def clear_report_info(request):
"""Empties the job_info dictionary"""
JOB_INFO["Plentific Job Number"].clear()
JOB_INFO["WorkOrder Number"].clear()
JOB_INFO["Invoice Number Found"].clear()
JOB_INFO["Payments"].clear()
JOB_INFO["Job Number Exists"].clear()
return redirect(reverse(data_entry))
html page
{% extends "base.html" %}
{% block content %}
{% load crispy_forms_tags %}
<div class="jumbotron">
<h1>Data Entry Tool:</h1>
<form action="{% url 'search_update_feedback' %}" method="GET">
{{ form|crispy }}
<button class="btn btn-success" type="submit" data-toggle="tooltip" data-placement="right" title="Updates the database with the info provided above">
Update and Fetch Info
</button>
</form>
<br>
<form action="{% url 'export_job_info_report' %}" method="GET">
<button class="btn btn-success" type="submit" data-toggle="tooltip" data-placement="right" title="Downloads the report below in .xlsx format">
Download Report
</button>
</form>
<br>
<form action="{% url 'clear_report_info' %}" method="GET">
<button class="btn btn-success" type="submit" data-toggle="tooltip" data-placement="right" title="Warning! You will lose all of the data below (does not affect database data)">
Clear Report - hover over me!
</button>
</form>
</div>
<hr>
{{ df_html | safe }}
{% endblock %}
urls
urlpatterns = [
path("", data_entry, name="data_entry"),
path("export_job_info_report/", export_job_info_report, name="export_job_info_report"),
path("clear_report_info/", clear_report_info, name="clear_report_info"),
]
Of course I have left out a whole lot of functionality to save reading time but please let me know if anything else can/should be added to help understand the issue.
Any help will be greatly appreciated.
I managed to solve this issue by replacing the JOB_INFO list with a new Django Model with the same field names, like this:
from django.db import models
class JobInfoReport(models.Model):
"""The following are prefixed with 'r' to represent report"""
r_plentific_job_number = models.CharField(max_length=7)
r_wo_number = models.CharField(max_length=6)
r_invoice_number_found = models.CharField(max_length=5)
r_payments = models.CharField(max_length=100)
r_job_number_exists = models.CharField(max_length=50)
def __str__(self):
return self.r_plentific_job_number

Redirecting buttons with values to other django templates/views

Firstly, I am getting a csv file from the user.
(Template file:)
<form method="post" action="{% url 'rowcol' %}" enctype="multipart/form-data">
{% csrf_token %}
<input type="file" name="file" accept=".csv">
<button type="submit">Upload File</button>
</form>
Then i am generating a list of all the columns present in the file and then calling another html file. (views.py:)
def rowcol(request):
if request.method == 'POST':
file = request.FILES['file']
dataset=pd.read_csv(file)
lst=list(dataset)
return render(request, 'Link5_rc.html', {'arr':lst})
return HttpResponse('')
In that html file, i am creating buttons for all the columns present.(Link5_rc.html:)
{% for link in arr %}
<form action=" " method="post">
<button name="{{link}}" type="submit" value="{{link}}">{{link}}</button>
</form>
{% endfor %}
Now the following is the part where i am stuck: I want these buttons to redirect to another html page or maybe a view in views.py , where i can show to the user which column he/she selected and then perform further actions on that particular column.
You can pass one or more values to the request as in the following example:
Some text
You can use variables like:
Some text
In your app urls.py you should set the following to receive the extra data in the request:
url(r'^your_name/(?P<value_1>[\d\D]+)$', views.your_view, name="your_url_alias")
Then, in your view function you should receive the data as in:
def your_view(request, value_1):
An then you can use the value to filter the queryset.

Preserve newlines in file rendered to HTML with Jinja

I am trying to print the content of a file in a web page. I want to print each line from the file on a separate line, but instead the line breaks are missing. How do I print the file and preserve newlines?
#app.route('/users')
def print_users():
v = open("users.txt","r").read().strip()
# also tried:
# v = open("users.txt","r").read().strip().split('\n')
return render_template('web.html', v=v)
{{ v|safe}}
You can use :
v = open("users.txt","r").readlines()
v = [line.strip() for line in v]
and then in your html something like (but feel free to play around with it):
<form action="/print_users" method="post" >
<div class="form-inline">
{% for line in v %}
<div>{{ line|safe}}</div>
{% endfor %}
<input class="btn btn-primary" type="submit" value="submit" >
</div>
</form>
While the other answers give great techniques and the current accepted solution works, I needed to do a similar task (rendering a text email template), but needed to extend this to preserve the processing of macros within the file, which led me to create what I think is the simplest and most elegant solution - using render_template_string.
def show_text_template(template_name):
"""
Render a text template to screen.
Replace newlines with <br> since rendering a template to html will lose the line breaks
:param template_name: the text email template to show
:return: the text email, rendered as a template
"""
from flask import render_template_string
txt_template = open(
'{}/emails/{}{}'.format(app.config.root_path + '/' + app.template_folder, template_name, '.txt'),
"r").readlines()
return render_template_string('<br>'.join(txt_template))

Django upload and process file with no data retention

Python: 2.7.11
Django: 1.9
I want to upload a csv file to Django and analyze it with a Python class. No saving is allowed and the file is only needed to reach the class to be analyzed. I'm using Dropzone.js for the form but I don't understand how I should configure/program the views to achieve this.
<form action="/upload/" method="post" enctype="multipart/form-data" class="dropzone" id="dropzone">
{% csrf_token %}
<div class="fallback">
<input name="file" type="file" multiple />
</div>
</form>
I have found an article about this but it describes saving and is based on Django 1.5.
view.py
def upload(request):
if request.method == 'POST':
file = FileUploadForm(request.POST)
if file.is_valid():
return HttpResponseRedirect('/upload/')
else:
file = FileUploadForm()
return render(request, 'app/upload.html', {'file': file})
forms.py
from django import forms
class FileUploadForm(forms.Form):
file = forms.FileField()
Closing Update:
The most important difference between the helping answer and my situation is that I had to decode my input.
See the following line as mine csv_file in handle_csv_data:
StringIO(content.read().decode('utf-8-sig'))
Access the csv file in the view function. If you are using python 3, you must wrap the InMemoryUploadedFile in a TextIOWrapper to parse it with the csv module.
In this example the csv is parsed and passed back as a list named 'content' that will be displayed as a table.
views.py
import csv
import io # python 3 only
def handle_csv_data(csv_file):
csv_file = io.TextIOWrapper(csv_file) # python 3 only
dialect = csv.Sniffer().sniff(csv_file.read(1024), delimiters=";,")
csv_file.seek(0)
reader = csv.reader(csv_file, dialect)
return list(reader)
def upload_csv(request):
csv_content=[]
if request.method == 'POST':
csv_file = request.FILES['file'].file
csv_content = handle_csv_data(csv_file)
return render(request, 'upload.html', {'content':content})
Your original code did not use django's form framework correctly, so I just dropped that from this example. So you should implement error handling when the uploaded file is invalid or missing.
upload.html
<form action="/upload/"
method="post"
enctype="multipart/form-data"
class="dropzone"
id="dropzone">
{% csrf_token %}
<div class="fallback">
<input name="file" type="file"/>
<input type="submit"/>
</div>
</form>
{% if content %}
<table>
{% for row in content %}
<tr>
{% for col in row %}
<td>{{ col }}</td>
{% endfor %}
</tr>
{% endfor %}
</table>
{% endif %}
I've added a 'submit' button so this works without the dropzone thing. I also removed 'multiple' from the file input, to keep the example simple. Finally there's a table if the template receives content from a parsed csv. But when using dropzone.js, you have to use a javascript callback function to display the table.

Categories