I have a problem with my code.
I'm trying to create a docx generator with docxtpl and flask, but I can't get it to work. My intention is to download the file generated with the information acquired from the form.
Here is the code in app.py:
from docxtpl import DocxTemplate
from flask import Flask, render_template, request, redirect, send_from_directory, url_for, send_file
app = Flask(__name__)
#app.route('/', methods=['GET', 'POST',])
def index():
# generate_report()
return render_template('index.html')
#app.route('/', methods=['GET', 'POST']) # When the user click to the "submit" button
def download_file():
if request.method == 'POST':
result = request.form
doc = DocxTemplate("templates/template_procuracao.docx")
context = {
'autor':result['autor'],
'nacionalidade':result['nacionalidade'],
'estadocivil':result['estadocivil'],
'identidade':result['identidade'],
}
doc.render(context)
doc.save()
return send_file('templates/output',
attachment_filename='teste.docx',
as_attachment=True)
if __name__ == '__main__':
app.run()
Here is the code in index.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<form action="{{ url_for('index') }}" method="post">
<input type="text" id="autor" name="autor" placeholder="AUTOR"><br>
<input type="text" id="nacionalidade" name="nacionalidade" placeholder="NACIONALIDADE"><br>
<input type="text" id="estadocivil" name="estadocivil" placeholder="ESTADOCIVIL"><br>
<input type="text" id="identidade" name="identidade" placeholder="IDENTIDADE"><br>
Submit
</form>
</body>
</html>
after clicking the submit button nothing happens.
127.0.0.1 - - [06/Apr/2022 21:00:23] "GET / HTTP/1.1" 200 -
127.0.0.1 - - [06/Apr/2022 21:00:33] "GET / HTTP/1.1" 200 -
When you save your document you need to save it in memory to essentially create a file to send (unless you want to save it as a file and then load it again). You are also trying to send a file 'templates/output' and not the document you'd created.
from io import BytesIO
...
def download_file():
...
docx_in_memory = BytesIO()
doc.render(context)
doc.save(docx_in_memory)
docx_in_memory.seek(0)
return send_file(
docx_in_memory,
attachment_filename='teste.docx',
as_attachment=True)
Related
A string sample~text~11 is being passed as a parameter from index.html to plot.html using the Flask session.
I want to print the parameter using Brython on the page plot.html.
plot.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Plot</title>
<script type="text/javascript" src="../static/jquery/jquery-3.6.3.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.0.1/socket.io.js"></script>
<script src="../static/brython/Brython-3.11.1/brython.js"></script>
<script src="../static/brython/Brython-3.11.1/brython_stdlib.js"></script>
</head>
<body onload="brython()">
<script type="text/python">
from browser import document
document <= "Hello World!"
document <= document.query['plot_param']
</script>
<h1>Plot page</h1>
<h3>{{plot_param}}</h3>
<h3 id="my_h3"></h3>
</body>
</html>
The above page is supposed to show the string sample~text~11 (see index.html) twice.
However, it is not doing what it was supposed to do. Brython is not parsing the parameter. Therefore, the string is shown only once (rather than twice).
How can I achieve what I want?
.
.
Additional Source Code:
app.py
from flask import Flask, session, render_template
from flask_socketio import SocketIO
from flask import request, redirect
async_mode = None
app = Flask(__name__)
app.config["SESSION_PERMANENT"] = False
app.config["SESSION_TYPE"] = "filesystem"
app.secret_key = "super secret key"
socketio_obj = SocketIO(app)
#app.route('/', methods=['GET', 'POST'])
def index():
print("index()...called...")
if request.method == "POST":
print("POST method used ...")
if request.form.get('submit_button1'):
session["unique_key_str"] = request.form['text1']
return redirect("/plot")
# end-if
# end-if
return render_template('index.html')
# end-def
#app.route('/plot', methods=['GET', 'POST'])
def plot():
print("plot()...called...")
return render_template('plot.html', plot_param=session["unique_key_str"])
if __name__ == '__main__':
socketio_obj.run(app, debug=True)
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script type="text/javascript" src="../static/jquery/jquery-3.6.3.js"></script>
<script type="text/javascript" src="../static/jquery/jquery.redirect.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.0.1/socket.io.js"></script>
</head>
<body>
<form method="post" >
<input type="text" name="text1" value="sample~text~11" />
<input type="submit" name="submit_button1" value="Token value">
</form>
<h1>Index page</h1>
</body>
</html>
i have created a form for user input, and run it in app.py with flask. What i want to achieve is to be able to get the user data, and then save it to my mongodb database. This is my html for the form.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="../static/Recording.css">
</head>
<div class="header">
<h1>Create a recording</h1>
</div>
<body>
<div class="create">
<form name="formdata">
<label for="trolley">Trolley</label>
<input type="text" id=trolley name="trolley" size="180" required>
<label for="datetime">Date & time</label><br>
<input type="datetime-local" id="datetime" name="datetime"><br required>
<label for="temp">Temperature</label>
<input type="text" id="temp" name="temp" size="180" required>
<input id="button1" type="submit" value="Record"">
</form>
<script src="https://cdn.jsdelivr.net/npm/papaparse#5.2.0/papaparse.min.js"></script>
<script src="../static/Recording.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script src="../static/database.js"></script>
</body>
</html>
This is my app.py file
from flask import Flask, render_template, jsonify, json, request
from flask_pymongo import PyMongo
from pymongo import MongoClient
app = Flask(__name__)
#routes
from q2 import subroutes
client = MongoClient("mongodb+srv://Stanislas:reddevils97#tma.p1mbs.mongodb.net/<dbname>?retryWrites=true&w=majority")
db = client.get_database("smarttrolley")
records = db.recordings
#app.route("/")
def home():
return render_template('SmartTrolley.html')
#app.route("/userinput/")
def userInput():
return render_template('Recording.html')
if __name__=='__main__':
app.debug = True
app.run(port=5000)
'''
this is my subroutes.py file, which handles the user data and post it in the route "/data"
from flask import Flask
from app import app
from q2.models import User
#app.route("/data", methods=["POST"])
def data():
return User().input()
This is my models.py file, which collects the data from the "/data" route, which then proceeds to insert the data into my mongoDB database.
from flask import Flask, jsonify, request
from app import db, records
class User:
def input(self):
inputs = {
"_id": "",
"trolleyname": request.form.get('trolley'),
"Date & Time": request.form.get('datetime'),
"Temperature": request.form.get('temp')
}
db.records.insert_one(inputs)
return jsonify(inputs), 200
I am using jquery ajax call for the data to be sent. I am able to receive the data via the console.log everytime the user submits data, and everything is working fine. However, i am receiving the error "GET http://localhost:5000/data 404 (NOT FOUND)", which shows that they can't locate my "/data" route. Is anyone able to help me and find out whats wrong, because i have done the importing of the subroutes into my app.py and nothing seems to be working. thank you
It is only allowed for POST method in your code
#app.route("/data", methods=["POST"])
def data():
return User().input()
#You are using GET method here
GET http://localhost:5000/data 404 (NOT FOUND)
Either change above code to following:
#app.route("/data", methods=["GET"])
def data():
return User().input()
#Or you can hit POST request
How can you use flask to make the text of your website blue? I only know how to display text on your website. My code :
from flask import Flask
app = Flask(__name__)
#app.route('/')
def hello_world():
return '''Hello world'''
Despite the negative feedback from other user, this is not that bad of a question, besides apart of #go2nirvana no one answered your question.
Note
Despite this is more a Front-end question related to CSS or Javascript and not HTML (yes you can embed CSS inline within HTML but is not recommended) what you asked can be achieved in Flask in many ways.
Example 1 -Hard coding, not recommended buy you can do it-
from flask import Flask
app = Flask(__name__)
#app.route('/')
def hello_world():
my_html = '''
<body style="background-color: #e1eb34;">
<h1 style="color: #002aff;">Hello World</h1>
</body>
'''
return my_html
if __name__ == '__main__':
app.run(debug=True)
or
from flask import Flask
app = Flask(__name__)
#app.route('/')
def hello_world():
return '''
<body style="background-color: #e1eb34;">
<h1 style="color: #002aff;">Hello World</h1>
</body>
'''
if __name__ == '__main__':
Example 2 -Using Jinja2 DOCS##
from flask import Flask, render_template
app = Flask(__name__)
#app.route('/')
def hello_world():
color = {
'blue': '002aff',
'yellow': 'e1eb34',
'green': '28fc03',
'red': 'fc1703',
'purple': 'b503fc'}
return render_template('index.html', color=color)
if __name__ == '__main__':
app.run(debug=True)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body style="background-color: #{{color['yellow']}};">
{% for hue in color.values() if hue != 'e1eb34'%}
<h1 style="color: #{{hue}};">Hello World</h1>
{% endfor %}
<h1></h1>
</body>
</html>
Example 3 -Adding request, session, redirect, url_for and more fun
from flask import Flask, render_template, redirect, url_for, request, session
import random
app = Flask(__name__)
app.config['SECRET_KEY'] = 'dev'
color = {
'blue': '002aff',
'yellow': 'e1eb34',
'green': '28fc03',
'red': 'fc1703',
'purple': 'b503fc',
'orange': 'FF9733 ',
'black' : 'FFFFFF',
'light-blue': '0AE5E3',
'pink': 'FF95AE',
'blue-green' : '95FFCA'}
#app.route('/', methods=['GET', 'POST'])
def index():
error = None
if 'color' not in session:
session['color'] = None
session['background'] = None
if request.method == 'POST':
choice = request.form['color'].lower()
if choice not in color:
error = 'Color not in list'
return render_template('index.html', color=session['color'], background=session['background'], error=error )
else:
session['color'] = color.get(choice)
session['background'] = random.choice(list(color.values()))
return redirect(url_for('index'))
return render_template('index.html', color=session['color'], background=session['background'], error=error )
if __name__ == '__main__':
app.run(debug=True)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
{% if color%}
<style>
body {
color: #{{color}};
background-color: #{{background}};
}
</style>
{% endif %}
</head>
<body>
<h1>Hello World</h1>
{% if error%}
{{error}}
{% endif %}
<form action="{{url_for('index')}}" method="POST">
<label for="color">Choose a color</label>
<input type="text" name="color">
<input type="submit" value="PRESSS" name="i_talk-with_flask">
</form>
</body>
</html>
Variation with a Macro DOC
{% macro color_mix(color)%}
{% if color%}
<style>
body {color: #{{color}};}
body {background-color: #{{background_}};}
</style>
{% endif %}
{% endmacro%}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
{{color_mix(color)}}
</head>
<body>
<h1>Hello World</h1>
{% if error%}
{{error}}
{% endif %}
<form action="{{url_for('index')}}" method="POST">
<label for="color">Choose a color</label>
<input type="text" name="color">
<input type="submit" value="PRESSS" name="i_talk-with_flask">
</form>
</body>
</html>
Honestly this is only the tip of the iceberg of the option you can have. Now is this reccomended ? Probably not, because this it should be handle with CSS or then handle it with JavaScript.
However there may be planty of instances where you may want to use it from a Flask App, one of there are:
Testing Purposes.
Debugging.
Something related to a Database.
Fun
That's a CSS question, not Flask.
return '<span style="color: #00ccff;">Hello world</span>'
Answer to Question 2
I'm assuming that you mean taking an image from the web. Yes you can, but this is definitely a CSS/HTML related question. However following the same principle of my previous answer:
Picures taken from Unsplash
from flask import Flask, render_template
app = Flask(__name__)
#app.route('/')
def index():
my_pic = 'https://images.unsplash.com/photo-1469980098053-382eb10ba017?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1050&q=80'
return render_template('index.html', my_pic=my_pic)
if __name__ == '__main__':
app.run(debug=True)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body style="background-image: url(https://images.unsplash.com/photo-1600187734183-707cf1c0fd5a?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1304&q=80);"
>
< <div>
<h1 style="color: white;">Picture from HTML</h1>
<img src="https://images.unsplash.com/photo-1600298881979-9b0c50d7abdf?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=400&q=60" alt="opps">
</div>
<div style="color: white;">
<h1>Picture from Flask</h1>
<img src="{{my_pic}}" alt="oops">
</div>
</body>
</html>
I suggest you to learn it from HTML and CSS related topic rather than Flask (first learn some CSS and HTML basic):
CSS
HTML
That been said I have a more interesting a USEFUL answer that however requires basic knowledge of the use of a Database, I assume you are a beginner and you may have not yet this knowledge but soon or later you will. So even if you dont understand completely the following keep it in mind and come back later.
I prepared a mini app that using flask, flask_sqlalchemy (with sqlite3), html and Bootstrap.
This app does the following and will teach you these principle:
.1 Upload a picture into a Database.
.2 How to download a picture from the Database.
.3 Render the picture from the Database into the WebBroser.
FULL CODE FROM GITHUB
Some Code from this mini app
Initiate the database, configs and Picture table for the databse
In class FileContent(db.Model):
data = file.read() It saves in database the Binary version of thefile
-render_file = render_picture(data). It saves the decode version, so that you can you see it for render it in the webpages.
# Built-in Imports
import os
from datetime import datetime
from base64 import b64encode
import base64
from io import BytesIO #Converts data from Database into bytes
# Flask
from flask import Flask, render_template, request, flash, redirect, url_for, send_file # Converst bytes into a file for downloads
# FLask SQLAlchemy, Database
from flask_sqlalchemy import SQLAlchemy
basedir = 'sqlite:///' + os.path.join(os.path.abspath(os.path.dirname(__file__)), 'data.sqlite')
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = basedir
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
app.config['SECRET_KEY'] = 'dev'
db = SQLAlchemy(app)
# Picture table. By default the table name is filecontent
class FileContent(db.Model):
"""
The first time the app runs you need to create the table. In Python
terminal import db, Then run db.create_all()
"""
""" ___tablename__ = 'yourchoice' """ # You can override the default table name
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(128), nullable=False)
data = db.Column(db.LargeBinary, nullable=False) #Actual data, needed for Download
rendered_data = db.Column(db.Text, nullable=False)#Data to render the pic in browser
text = db.Column(db.Text)
location = db.Column(db.String(64))
pic_date = db.Column(db.DateTime, nullable=False, default=datetime.utcnow)
def __repr__(self):
return f'Pic Name: {self.name} Data: {self.data} text: {self.text} created on: {self.pic_date} location: {self.location}'
Upload route, here is where the picture its sent to databse and processed with correct data
So here is what is going on in the app route:
def render_picture(data) --> Takes the bites raw version of the pic and return the decode version, so that it can be used to be display on the web.
data = file.read() : This is the raw data.This can be used for downloading the pic from database
render_file: decoded file so you can retrieve it and the render in the web page
#Render the pics, this Function converts the data from
request.files['inputFile'] so that in can be displayed
def render_picture(data):
render_pic = base64.b64encode(data).decode('ascii')
return render_pic
#app.route('/upload', methods=['POST'])
def upload():
file = request.files['inputFile']
data = file.read()
render_file = render_picture(data)
text = request.form['text']
location = request.form['location']
newFile = FileContent(name=file.filename, data=data,
rendered_data=render_file, text=text, location=location)
db.session.add(newFile)
db.session.commit()
flash(f'Pic {newFile.name} uploaded Text: {newFile.text} Location:
{newFile.location}')
return render_template('upload.html')
INDEX Route
# Index It routes to index.html where the upload forms is
#app.route('/index', methods=['GET', 'POST'])
#app.route('/')
def index():
return render_template('index.html')
INDEX HTML with the Form
<form method="POST" action="/upload" enctype="multipart/form-data">
<!-- File Upload-->
<div class="form-group">
<label for="inputFile">File input</label>
<input class="form-control-file" type="file" name="inputFile">
</div>
<!-- Location -->
<div class="form-group">
<label for="location">Location</label>
<input class="form-control" type="text" name="location">
</div>
<!-- Text -->
<div class="form-group">
<label for="text">Write Text</label>
<textarea class="form-control" name="text" id="text" rows="5" placeholder="Add a Description"></textarea>
</div>
<!-- Submit -->
<button type="submit" class="btn btn-primary">Submit</button>
</form>
I work with the Python flask, HTML, and local JSON file to display the JSON data from a local JSON file in the HTML. Once the flask reads a local JSON file, it is sent to index.html with jsonify. After then, using that data I want to display the information.
I can the JSON data in the flask side, but have struggled with displaying it in the HTML. Could you let me know what I missed?
flask code
import os
from flask import Flask, render_template, abort, url_for, json, jsonify
import json
import html
app = Flask(__name__)
# read file
with open('./data/file.json', 'r') as myfile:
data = myfile.read()
#app.route("/")
def index():
return render_template('index.html', title="page", jsonfile=jsonify(data))
app.run(host='localhost', debug=True)
index.html
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta charset="UTF-8" />
<title>House</title>
<link
rel="stylesheet"
href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css"
integrity="sha384-1q8mTJOASx8j1Au+a5WDVnPi2lkFfwwEAa8hDDdjZlpLegxhjVME1fgjWPGmkzs7"
crossorigin="anonymous"
/>
<script>
var jsonfile ={{jsonfile}};
</script>
</head>
<body>
<div class="container">
{{jsonfile}}
</div>
</body>
</html>
Your issue is the use of the jsonify method. If you read the documentation of jsonify it returns a Response object and not a string. So you will get something like this for jsonify(data)
<Response 2347 bytes [200 OK]>
You could remove jsonify and use json.dumps instead, as follows:
#app.route("/")
def index():
return render_template('index.html', title="page", jsonfile=json.dumps(data))
This works for me.
What Rahul P is correct and the reason you are getting unexpected results is because you are using jsonify when you should be using json.dumps(data).
If you want you want to use the json inside of the script tag can I suggest making the following changes?
app.py
import os
from flask import Flask, render_template, abort, url_for
import json
import html
app = Flask(__name__)
# read file
with open('./data/file.json', 'r') as myfile:
data = myfile.read()
#app.route("/")
def index():
return render_template('index.html', title="page", jsonfile=json.dumps(data))
if __name__ == '__main__':
app.run(host='localhost', debug=True)
index.html
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta charset="UTF-8" />
<title>House</title>
<link
rel="stylesheet"
href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css"
integrity="sha384-1q8mTJOASx8j1Au+a5WDVnPi2lkFfwwEAa8hDDdjZlpLegxhjVME1fgjWPGmkzs7"
crossorigin="anonymous"
/>
</head>
<body>
<div class="container"></div>
<script>
const jsonfile = JSON.parse({{jsonfile|tojson}});
console.log(jsonfile);
document.querySelector(".container").innerHTML = JSON.stringify(jsonfile, null, 2);
</script>
</body>
</html>
I have a Flask app where I want to click a button on the home page, which will
On click, run Python script and route to my results.html. (which i have done)
Auto-fill certain fields on that page with results from a python script. (what i need help with)
The python script (parser.py) may take a 30-40 minutes to run, as its job is to start a test that takes about that long, then process and grab/parse the results. After that, some other fields will be filled in by the user, then the form on results.html is submitted to a database.
I hope i'm closer to my answer than I think, but where/how do I introduce my python into this and pass it into the form on results.html?
parser.py
import csv
import pandas as pd
import numpy as np
# Test data
body = pd.read_csv('path-to-test-data.csv', skiprows=11)
# Build dataframe of test info
frame = body['Frame Size']
loss = body['Loss Rate (Percent)']
speed = body['Tx Rate (L1) (Bit/s)']
grade = body['Result State']
lst = pd.concat([frame,loss,speed,grade], axis = 1)
selected_df = pd.DataFrame(data=lst)
selected_df.set_index('Frame Size')
# Select all 64b frame results
print(selected_df[np.isclose(selected_df['Frame Size'].values[:, None], [64],).any(axis=1)])
# Select all tests that fail
print(selected_df.loc[selected_df['Result State'] == 'FAIL'])
app.py:
import os
from flask import Flask, escape, request, redirect, render_template
app = Flask(__name__)
#app.route('/')
def home():
return render_template('index.html')
#app.route('/results/')
def about():
return render_template('results.html')
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>OLT TESTER</title>
</head>
<body>
<div class="index">
Press This Button to Begin Testing
<button onclick=""></button>
</div>
</body>
</html>
results.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Results</title>
</head>
<body>
<div class="results">
Initialize Test
<form action="#.php" method="post">
Job Order: <input type="text" name="jobOrder"><br>
Serial Number: <input type="text" name="serialNo"><br>
Frame Size: <input type="text" name="jobOrder"><br> <!--Fill this field with Python output -->
Result State: <input type="text" name="serialNo"><br> <!--Fill this field with Python output -->
<input type="submit">
</form>
</div>
</body>
</html>