Download dataframe as excel using FastAPI at custom location - html

I am new to FastAPI and I need to understand if there is a way to download a dataframe in excel format at user selected location in their system. Below is the sample code I wrote but for downloading the dataframe as excel, I had to hardcode the system location in the code.
main.py code :
from fastapi import FastAPI, Request, Form
from pydantic import BaseModel
from fastapi.responses import HTMLResponse
from fastapi.templating import Jinja2Templates
import uvicorn
import pandas as pd
app = FastAPI()
templates = Jinja2Templates(directory="htmlDirectory")
class NameValues(BaseModel):
Name : str = None
def save_to_excel(content, filename):
file = content.to_excel(r"E:\PycharmProjects"+"\\"+filename+".xlsx", index=False)
return file
#app.get("/home", response_class = HTMLResponse)
def home(request:Request):
return templates.TemplateResponse("introduction.html", {"request": request})
#app.post("/displayDF")
async def handle_df(request: Request, Name: str = Form(...), action: str = Form(...)):
if action == "Submit":
test_list = [["Joe", 34, "Accounts", 10000], ["Jack", 34, "Chemistry", 20000]]
data = pd.DataFrame(data=test_list, columns=["Name", "Age", "Dept.", "Salary"])
return templates.TemplateResponse(
'df_representation.html',
{'request': request, 'data': data.to_html()}
)
if action == "Download":
test_list = [["Joe", 34, "Accounts", 10000], ["Jack", 34, "Chemistry", 20000]]
data = pd.DataFrame(data=test_list, columns=["Name", "Age", "Dept.", "Salary"])
save_to_excel(data, Name)
return "File Downloaded successfully"
if __name__ == '__main__':
uvicorn.run('main:app', host='0.0.0.0', port=8000)
df_representation.html code :
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>displayDF</title>
</head>
<body>
<h2>DataFrame representation:</h2>
<!-- You've to mark your data as safe,
otherwise it'll be rendered as a string -->
{{ data|safe }}
<form action="/displayDF" method="post">
<input type="text" name="Name">
<input type="submit" name="action" value="Download">
</form>
</body>
</html>
introduction.html code :
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Home</title>
</head>
<body>
<h2>Please enter a string in the space provided</h2>
<form action="/displayDF" method="post">
<input type="text" name="Name">
<input type="submit" name="action" value="Submit">
</form>
</body>
</html>
The above code works fine but the only problem is that I have hardcoded location in save_to_excel method in main.py file. I need to change the code in such a way that user could select the desired location in their system and let program know where they want the dataframe downloaded in excel format. Thanks in advance for all the help!!

Related

Why can't my flask app.py render_template a html file on chrome extension popup?

I have the following app.py code
from flask import Flask, render_template, request, jsonify
import numpy as np
from joblib import load
import pandas as pd
app = Flask(__name__)
#app.route("/")
def home():
return render_template("index.html")
#app.route('/predict', methods=['POST'])
def predict():
t = request.form['reviewfield']
text = [t]
pipeline = load("ModelSVMNew.joblib")
pred = pipeline.predict(text)
return render_template('after.html', data=pred)
if __name__ == "__main__":
app.run(port=3000, debug=True)
and i want a form to submit the text from chrome extension to predict function and render the html in place of the popup.html (as in manifest.json). now this works with a normal web page on local host but gives an error that the file is not accessible when doing the same on chrome extension.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Fake Review Detection</title>
</head>
<body>
<center>
<h1>Fake Review Detection</h1>
<form action="{{url_for('predict')}}" method="post">
<b> Enter Review: <input type="text" name="reviewfield" /></b> <br />
<br />
<input type="submit" value="Predict" />
</form>
</center>
</body>
</html>

Pass Jinja2 template as html string while rendering using FastAPI?

My template is as follows:
<!-- template1.html -->
<html>
<head>
<title>Item Details</title>
</head>
<body>
<p>{{ req }}</p>
</body>
</html>
To render the template I am using the following code:
from fastapi import FastAPI
from fastapi.templating import Jinja2Templates
app = FastAPI()
template = Jinja2Templates(directory="templates")
#app.get("/list_items")
def home(request: Request):
return template.TemplateResponse('template1.html',{"req": req})
#app.get("/", response_class=HTMLResponse)
async def read_items():
return """
<html>
<head>
<title></title>
</head>
<body>
<form action="/list_items">
<input type="text" placeholder="Search.." name="search">
<button type="submit">Search</button>
</form>
</body>
</html>
"""
But I do not want to use a separate folder with files for a simple template. How do I pass the html text instead of the function TemplateResponse
You can use HTMLResponse. Pass HTMLResponse as the parameter response_class of your route.
from fastapi import FastAPI
from fastapi.responses import HTMLResponse
app = FastAPI()
#app.get("/items", response_class=HTMLResponse)
def read_items():
return """
<html>
<head>
<title>Some HTML in here</title>
</head>
<body>
<h1>Look ma! HTML!</h1>
</body>
</html>
"""
You can also override the response directly in your endpoint, by returning it.
from fastapi import FastAPI
from fastapi.responses import HTMLResponse
app = FastAPI()
#app.get("/items")
def read_items():
html_content = """
<html>
<head>
<title>Some HTML in here</title>
</head>
<body>
<h1>Look ma! HTML!</h1>
</body>
</html>
"""
return HTMLResponse(content=html_content, status_code=200)
Update
Jinja2Templates.TemplateResponse expects as name parameter a filename that is pointing to the template your would like to return, and which lies in the Jinja2Templates directory you defined (e.g., Jinja2Templates(directory="templates") ). You can't pass the template contents to its place. Jinja2Templates will attempt to retrieve the file you passed using the directory you defined earlier, see here -> here -> here. Hence, what you are asking, it doesn't seem to be natively possible (but, with some hackish stuff maybe doable); however, there is nothing wrong with having a templates directory, even for small template files.

GET data from HTML and process in python using Flask and POST back in same HTML

hi i am trying to implement a chat type module. My front end in a HTML page from which i GET a data. The obtained data is passed to python flask. And finally the processed data must be posted back to the same HTML page.
I am able to GET the data. But unable to post it back to the same HTML page.
the following is the HTML code
<html>
<head>
<meta charset="UTF-8">
<script type="text/javascript" src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
<script>
function ajaxcall(){
var p_name = $('#p_name').val();
var p_email = $('#p_email').val();
$.post("http://127.0.0.1:5000/getdata?chatbox="+p_name);
}
</script>
</head>
<form action="" method="POST" name='chat'>
<div>
{{text_typed}}
</div>
Enter Chat: <textarea id="p_name" name="chatbox" rows="4" cols="50"></textarea>
<input type="button" onclick="ajaxcall()" value="submit me!" />
<label name='get_test' id='get_test'></label>
</form>
</html>
the value entered in the text area must be posted in {{text_typed}}. i am unable to get this
this is my python flask coding [i am performing this in a local environment]
from flask import Flask, jsonify, request, render_template, flash, url_for, redirect #import objects from the Flask model
app = Flask(__name__) #define app using Flask
#app.route('/')
def hello():
print("hello")
return "Welcome to mychat.in"
#app.route('/chat', methods=['GET', 'POST'])
def chat():
return render_template("getpost.html")
#app.route('/getdata', methods=['GET', 'POST'])
def getdata():
print('hi')
text_typed = request.args.get('chatbox')
print(text_typed)
return render_template("getpost.html", text_typed = text_typed)# this is the line i am trying to post back in html
if __name__ == '__main__':
app.run()
Thanks in advance.
Update your JS code:
$.post("http://127.0.0.1:5000/getdata?chatbox="+p_name);
According to the jQuery documentation you should put it as
$.post("http://127.0.0.1:5000/getdata?chatbox="+p_name, null, function(data) {
Put your code to insert returned _data_ into the form here.
});

Error : End of script output before headers while submiting html form in python-cgi

I am trying to create a form and getting the data entered by user into my script using python-cgi but I am getting this error message "End of script output before headers: processname.cgi". I have followed various blogs and tutorials but couldn't make it work.
Here is my form and cgi script. I am using python3 and xampp server on my local machine(MAC OSX)
form.html
<DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title>Get name from User</title>
</head>
<body>
<form method="post" action="processname.cgi">
Please Enter Your name: <input type="text" name="username" placeholder="e.g. John" autofocus
required="required"/>
<br>
<input type="submit" name="submitname" value="Submit"/>
</form>
</body>
</html>
And this is my cgi-script: processname.cgi
#!/usr/local/bin/python3
import cgi
import cgitb
cgitb.enable()
def htmlTop():
print('''Content-type:text/html\n\n
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8"/>
<title>My Server Side template</title>
</head>
<body>''')
def htmlTail():
print('''</body>
</html>''')
def getData():
formData = cgi.FieldStorage()
firstname = formData.getvalue("username")
return firstname
if __name__ == '__main__':
try:
htmlTop()
firstname = getData()
print("Hello {0}".format(firstname))
htmlTail()
except:
cgi.print_exception()
I figured it out.You have to make your script executable and then restart the server.
chmod 705 .../folders/scriptname.cgi
will make the script executable.

Django form not being submitted

I have a Django model/view/form that is rendering correctly in the template, but it is not submitting the data that is input to the database. Any help with this would be greatly appreciated!
#models.py
from django.db import models
from django.forms import ModelForm
class UserRegistration(models.Model):
user_first = models.CharField(max_length=50)
user_last = models.CharField(max_length=50)
user_email = models.EmailField()
#user_fantasyhost = models.CharField(max_length=50)
def __unicode__(self):
return u'%s %s %s' % (self.user_first, self.user_last, self.user_email)
class RegForm(ModelForm):
class Meta:
model = UserRegistration
#views.py
from django.shortcuts import render_to_response
from django.shortcuts import render
from django.http import HttpResponse, HttpRequest, HttpResponseRedirect
from acme.dc_django.models import UserRegistration
from acme.dc_django.models import RegForm
def regPage(request, id=None):
form = RegForm(request.POST or None,
instance=id and UserRegistration.objects.get(id=id))
if request.method == 'POST' and form.is_valid():
form.save()
return HttpResponseRedirect('/league_setup/')
user_info = UserRegistration.objects.all()
context = {
'form':form,
'user_info' :user_info,
}
return render(request, 'regpage.html', context)
#repage.html
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<HTML lang="en">
<head>
<title>User Registration</title>
</head>
<body>
<form method="POST" action="/league/">
{% csrf_token %}
<table>{{ form }}</table>
<input type="submit" value="Create Account"
</form><br /><br />
</body>
</HTML>
Thank you for your help,
dp
I tried your code. Your problem is that the action attribute of your html form tag is set to "/league/".
Unless reqPage url is actually "/league/", it won't work. When i changed action="/league/" to action="" as such:
<HTML lang="en">
<head>
<title>User Registration</title>
</head>
<body>
<form method="POST" action="">
{% csrf_token %}
<table>{{ form }}</table>
<input type="submit" value="Create Account" />
</form><br /><br />
</body>
</HTML>
The form did work:
In [3]: UserRegistration.objects.all()
Out[3]: [<UserRegistration: aoeu oeu oeu#aeou.com>]