Vishnu
Vishnu

Reputation: 65

Receiving a CSV dataset in python Flask

I am having a python program that receives a CSV file (using pandas.read_csv option) from the user and returns the size of the CSV file as output.

My requirement is to have a GUI with an upload button and show the size of dataset in that GUI itself. I am a beginner in Python and Flask. Could anyone guide me here how to achieve this requirement in Python Flask?

I tried the following code but it says "Internal Server Error" and I don't know how to implement upload button.

import pandas as pd 
from flask import Flask 
app = Flask(__name__)

@app.route('/') 
def data_shape():
    data = pd.read_csv('iris.csv') # there should be an upload option / button for this dataset in the flask webservice
    return data.shape

if __name__ == '__main__':   
app.run(host='0.0.0.0')

I have to upload the csv file in the webservice and get the output of the python code in the webservice itself.

Upvotes: 3

Views: 1290

Answers (1)

Pygirl
Pygirl

Reputation: 13349

app.py

import os
import shutil

from flask import Flask, flash, request, redirect, render_template
from werkzeug.utils import secure_filename
from flask import Flask, session
from fastai.vision import *

basedir = os.path.abspath(os.path.dirname(__file__))

UPLOAD_FOLDER = os.path.join('static', 'csv')

app = Flask(__name__)
app.secret_key = "secret key"
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
app.config['MAX_CONTENT_LENGTH'] = 16 * 1024 * 1024

ALLOWED_EXTENSIONS = set(['csv','xls'])


def allowed_file(filename):
    return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS


@app.route('/')
def upload_form():
    return render_template('index.html')

@app.after_request
def add_header(response):
    """
    Add headers to both force latest IE rendering engine or Chrome Frame,
    and also to cache the rendered page for 10 minutes.
    """
    response.headers['X-UA-Compatible'] = 'IE=Edge,chrome=1'
    response.headers['Cache-Control'] = 'public, max-age=0'
    return response    


@app.route('/', methods=['POST'])
def upload_file():

    # shutil.rmtree(UPLOAD_FOLDER)
    # os.mkdir(UPLOAD_FOLDER)
    disp_div = 'none'
    disp_div_tumor = 'none'

    d = request.form.to_dict()
    # print("dddd;",d)
    button_name = 'None'
    if (len(d)!=0):
        button_name = list(d.items())[-1][0]

    file = request.files['file']
    print("file:",file)
    if file.filename == '':
        flash('No file selected for uploading','red')
        # return redirect(request.url)
        return render_template('index.html', disp_div = disp_div)
    if file and allowed_file(file.filename):
        filename = secure_filename(file.filename)
        shutil.rmtree(UPLOAD_FOLDER)
        os.mkdir(UPLOAD_FOLDER)
        file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
        flash('File successfully uploaded!', 'green')
        print(UPLOAD_FOLDER)
        print("==>",os.path.join(UPLOAD_FOLDER, sorted(os.listdir(app.config['UPLOAD_FOLDER']))[0]))
        csv_file = pd.read_csv(os.path.join(UPLOAD_FOLDER, sorted(os.listdir(app.config['UPLOAD_FOLDER']))[0]))
        csv_shape = csv_file.shape

        return render_template('index.html', csv_shape=csv_shape)
        # return redirect('/')
    else:
        flash('Allowed file types are txt, pdf, png, jpg, jpeg, gif', 'red')
        # return redirect(request.url)
        return render_template('index.html')


if __name__ == '__main__':
    app.run(debug=False, port=5006)

## For deploying the app use `app.run(debug=False, host="0.0.0.0", port=80)`

templates/index.html

<link rel="stylesheet" type="text/css" href="/static/css/main.css">

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="static/js/index.js"></script>
<script>
  $(document).ready(function(){
    $("#target").on('submit',function(){
        // alert("It works");
    });
  });
</script>
<!doctype html>

<html>
<head>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">

</head>
<body>

    <form id="target" method="post"  enctype="multipart/form-data">
      <div name ="up" class="upload-btn-wrapper">
        <button name="upload" class="btn">Upload CSV File</button>
        <input type="file" id="file" value="go" name="file" onchange="$('#target').submit();"/>
      </div>
    </form>

    <p>
       {% with messages = get_flashed_messages(with_categories=true) %}
         {% if messages %}
          <div class=flashes>
          {% for category_color, message in messages %}
            <p class="error_text" style="color:{{ category_color }};width:500px;">{{ message }}</p>
          {% endfor %}
          </div>
         {% endif %}
       {% endwith %}
    </p>

    ===> {{ csv_shape }}
</body>
</html>

static/css/main.css:

.upload-btn-wrapper {
  position: absolute;
  overflow: hidden;
  display: inline-block;
  top:0;
  left:5%;
}    
.btn {
    width: 15vw;
    height: 4vh;
    padding: 0 0 2px;
    font-size: 2.2vh;
    /* font: 90% "Trebuchet MS", Tahoma, Arial, sans-serif; */
    font-family: sans-serif;
    font-weight: bold;
    line-height: 32px;
    text-transform: uppercase;
    margin: 0.2em auto;
    display: block;
    outline: none;
    position: relative;
    cursor: pointer;
    border-radius: 3px;
    color: #ffffff;
    text-shadow: 1px 1px #024bde;
    border: 1px solid #507def;
    border-top: 1px solid #2f73ff;
    border-bottom: 1px solid #2a67ff;
    box-shadow: inset 0 1px #4a82ff, inset 1px 0 #2653b9, inset -1px 0 #2d69e8, inset 0 -1px #4372e8, 0 2px #1c3d9e, 0 6px #2553a2, 0 4px 2px rgba(0,0,0,0.4);
    background: -moz-linear-gradient(top, #cae285 0%, #a3cd5a 100%);
    background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#cae285), color-stop(100%,#a3cd5a));
    background: -webkit-linear-gradient(top, #6292ff 0%,#2b6cff 100%);
    background: -o-linear-gradient(top, #cae285 0%,#a3cd5a 100%);
    background: -ms-linear-gradient(top, #cae285 0%,#a3cd5a 100%);
    background: linear-gradient(top, #cae285 0%,#a3cd5a 100%);
    filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#cae285', endColorstr='#a3cd5a',GradientType=0 );
    background-color: #1c3c9e;
}
.btn::-moz-focus-inner{border:0}

.btn:active {
    /*top: 3px;*/
/*    border: 1px solid #88A84E;
    border-top: 1px solid #6E883F;
    border-bottom: 1px solid #95B855;
    background: #A7CF5F;*/
    box-shadow: inset 0 1px 2px #779441;
    transform: translateY(3px);
}


.pred {
    position: absolute;
    left: 10%;
    bottom: 0;
}

.upload-btn-wrapper input[type=file] {
  font-size: 100px;
  position: absolute;
  left: 0;
  top: 0;
  opacity: 0;
}

.submit_btn {
  border: 2px solid gray;
  color: gray;
  background-color: white;
  padding: 8px 20px;
  border-radius: 8px;
  font-size: 20px;
  font-weight: bold;
}

.error_text {
  position: absolute;
  top: 2.7vh;
  font-weight: bold;
  font-size: 2vh;
  left: 5%;
}

Directory structure:

|-- fapp.py
|-- static
|   |-- css
|   |   `-- main.css
|   `-- csv
`-- templates
    `-- index.html

enter image description here

Edit: enter image description here

Upvotes: 2

Related Questions