python flask with json - python

I am trying to get user's input and return the details as json.
But I get an error and I can't find why.
Hers is my python code:
from flask import Flask, request, render_template,jsonify
import json
#app.route('/user_input')
def user_input():
return render_template('user-input.html')
#app.route('/user_input',methods = ['POST'])
def result():
NAME = request.form['Book_Name']
PAGE = request.form['Page']
TEXT = request.form['Text']
TOPIC = request.form['Topic']
pythonDictionary = {'bookName': NAME, 'page': PAGE, 'text': TEXT, 'topic': TOPIC}
dictionaryToJson = json.dumps(pythonDictionary)
return jsonify(dictionaryToJson)
and my HTML file:
<html>
<body>
<form action = "http://localhost:5000/result" method = "POST">
<p>Book Name <input type = "text" name = "Book_Name" /></p>
<p>Page <input type = "text" name = "Page" /></p>
<p>Text <input type = "text" name = "Text" /></p>
<p>Topic <input type ="text" name = "Topic" /></p>
<p><input type = "submit" value = "submit" /></p>
</form>
</body>
</html>
How can I return the values properly?

You are dumping the dict twice as jsonify also does json.dumps() (it also sets the correct response headers for you in addition which is why you should use it instead of json.dumps():
dictionaryToJson = json.dumps(pythonDictionary)
return jsonify(dictionaryToJson)
Do this:
from flask import Flask, request, render_template,jsonify
import json
#app.route('/user_input')
def user_input():
return render_template('user-input.html')
#app.route('/user_input',methods = ['POST'])
def result():
NAME = request.form['Book_Name']
PAGE = request.form['Page']
TEXT = request.form['Text']
TOPIC = request.form['Topic']
pythonDictionary = {'bookName': NAME, 'page': PAGE, 'text': TEXT, 'topic': TOPIC}
return jsonify(pythonDictionary )

0) Do not use uppercase for vars. Uppercase is always for constants.
1) Use routes with "/" at the end to avoid additional redirects which flask does:
#app.route('/user_input/', methods = ['POST'])
2) Use the same route and the same function to get what you need:
from flask import Flask, request, render_template, jsonify
def json_response(status_code, data):
res = jsonify(data)
res.status_code = status_code
return res
app = Flask(__name__)
#app.route('/user_input/', methods=["GET", "POST"])
def user_input():
if request.method == "GET":
return render_template('user-input.html')
else:
python_dictionary = {'bookName': request.form.get('Book_Name'),
'page': request.form.get('Page'),
'text': request.form.get('Text'),
'topic': request.form.get('Topic')}
return json_response(200, python_dictionary)
app.run()
3) And yes, you don't need to use json.dumps(pythonDictionary) before passing dictionary to jsonify
4) Consider to use request.form.get('key') rather than request.form['key'] because get() function returns None if there is no such key:value instead of raising key error exception.

Related

I want to update a database by loading a file into an already existing field, but an error occurs

My code:
from flask import Flask, render_template, url_for, request, redirect, send_file
from flask_sqlalchemy import SQLAlchemy
from datetime import datetime
from io import BytesIO
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///filestorage.db'
db = SQLAlchemy(app)
class FileContents(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(300))
date = db.Column(db.String(300), default=datetime.utcnow)
content = db.Column(db.LargeBinary)
def __repr__(self):
return '<File %r>' % self.id
#app.route('/')
def index():
files = FileContents.query.filter(FileContents.content == None).all()
return render_template('index.html', files=files)
#app.route('/upload/<int:id>', methods=['GET','POST'])
def upload(id):
file = FileContents.query.get_or_404(id)
if request.method == 'POST':
file.content = request.files['content']
db.session.commit()
return redirect('/')
if __name__ == "__main__":
app.run(debug=True)
Html:
<form action="/upload/{{file.id}}" method="POST" enctype="multipart/form-data">
<input type="file" name="content" id="content" value="{{file.content}}">
<br>
<input type="image" src="static/css/upload.png" name="submit" width="50" height="50" alt="submit"/>
</form>
An error:
sqlalchemy.exc.StatementError
sqlalchemy.exc.StatementError: (builtins.TypeError) memoryview: a bytes-like object is required, not 'FileStorage'
[SQL: UPDATE file_contents SET content=? WHERE file_contents.id = ?]
[parameters: [{'content': <FileStorage: 'randomfile.docx' ('application/vnd.openxmlformats-officedocument.wordprocessingml.document')>, 'file_contents_id': 1}]]
the problem appears to be in this line:
file.content = request.files['content']
Is there any way to pass a "bytes-like object" so that it could be uploaded?
Figured it out! Had to put .read() after the problematic line.
file.content = request.files['content'].read()

Check object for elements inside it on Flask

There is a drop-down list of items. If send button is pressed, the elements of the object are handled and I get a certain result. I want to check if the object is empty, then redirect to another page?
The code:
html:
<form action = "" method = "POST" enctype = "multipart / form-data">
<select id = 'sel' name = 'sel' class = "selectpicker sel" multiple data-live-search = "true">
{% for elem in elements%}
<option id = "val" value = "{{elem}}"> {{elem}} </option>
{% endfor%}
</select>
<button> Send </button>
</form>
python:
# app.route ('/', methods = ['GET', 'POST'])
def index ():
if request.method == 'GET':
return render_template ('index.html', elements = elements) # get all the elements on the page
elif request.method == 'POST':
docs = request.form.getlist ('sel') # here I get the items selected from the list
result = handler.dosomething (docs) # handler function
return render_template ('handler.html', result = result)
else:
pass
How to check if docs is empty and there are no selected elements inside this variable, then when the button is pressed, redirect to another page, for example error.html?
You can add one more if statement. See below:
# app.route ('/', methods = ['GET', 'POST'])
def index ():
if request.method == 'GET':
return render_template ('index.html', elements = elements) # get all the elements on the page
elif request.method == 'POST':
docs = request.form.getlist ('sel')
if len(docs)>0:
result = handler.dosomething (docs)
return render_template('handler.html', result = result)
else:
return render_template('error.html')

how to connect python backend with flask and html&css

'''
app.py
from flask import Flask, render_template, request
from weather_backend import temperature_condition,clothes,feels_temperature,weather_description
app = Flask(__name__)
app.config["SECRET_KEY"] = "Secret-key"
#app.route("/")
def index():
return render_template("index.html")
#app.route("/dress")
def dress():
cityname = request.form.get("city_name")
temp = str(temperature_condition())
message = str(clothes())
feels = feels_temperature
description= weather_description
return render_template("dress.html", message=message, temp=temp, feels_temperature=feels,
weather_description=description )
if __name__ == "__main__":
app.run(debug=True)
'''
'''
weather_backend.py
import requests, json
import weatherMappingMessage
from app import dress
from keys import *
base_url = "http://api.openweathermap.org/data/2.5/weather?"
city_name =
complete_url = base_url + "appid=" + api_key + "&q=" + city_name + "&units=metric"
response = requests.get(complete_url)
'''
HTML file
'''
<body>
<div class="head">
<form action= "{{ url_for('dress') }}" class="form" method="GET">
<h1>Get Weather and Dresses according to the Weather</h1>
<div class = "form-box">
<input type="text" class="search-field location" name= "city_name" placeholder="Location...">
<button class="search-btn" type="button">Search</button>
</div>
</form>
</div>
</body>
'''
I need to get the form info(search) from HTML to the backend(city_name) and then to the flask(cityname)
I can get a message from the backend if try to get it but I can't get HTML form to the backend for processing
The problem I'm facing is that I can't get the form data from my HTML file to my backend for processing
basically, I need the cityname to the backend for getting my weather description
Short answer:
Because your form submission uses a get request, you can use request.args to get parsed contents of query string (see also):
cityname = request.args.get("city_name")
Long answer:
I'm sure you're asking for more than just this piece of code. I took the code you provided and added the missing pieces in-line (please don't do this for production code) and also passed cityname to render_template:
import logging
from datetime import datetime
from flask import render_template, request
from app import app, forms
#app.route("/")
def index():
return render_template("index.html")
#app.route("/dress")
def dress():
cityname = request.args.get("city_name")
# missing in example code
def temperature_condition():
return 'temp cond'
# missing in example code
def clothes():
return 'clothes'
feels_temperature = 'feels temp' # missing in example code
weather_description = 'weather desc' # missing in example code
temp = str(temperature_condition())
message = str(clothes())
feels = feels_temperature
description = weather_description
return render_template("dress.html", message=message, temp=temp, feels_temperature=feels,
weather_description=description, cityname=cityname) # also pass cityname
I created a minimalistic dress.html:
<html>
<body>
<p>message = {{ message }}</p>
<p>temp = {{ temp }}</p>
<p>feels_temperature = {{ feels_temperature }}</p>
<p>weather_description = {{ weather_description }}</p>
<p>cityname = {{ cityname }}</p>
</body>
</html>
Starting the application via flask run allows me to input a city name into the form field and view the results (for example 'Berlin'):
In order to show the weather description for the chosen city, you could create a function that accepts the city name and retrieves the information from the web (just a rough sketch):
import requests, json
import weatherMappingMessage
from app import dress
from keys import *
def weather_for_city(city_name):
base_url = "http://api.openweathermap.org/data/2.5/weather?"
complete_url = base_url + "appid=" + api_key + "&q=" + city_name + "&units=metric"
response = requests.get(complete_url)
if response.status_code == 200:
return response.json() # assumes your API returns a JSON response
else:
# perform some error handling here, maybe apply a retry strategy
pass
Extract the relevant data from the result of weather_for_city and pass it to render_template like you did for the other variables.

Build a simple form to submit a name. Then go to another page which says Hello, name. in flask

so I get this error
"Could not build URL for endpoint 'success'. Did you forget to specify values ['name']?"
what is do be done to rectify this
This is the main snippet if the server.py
from flask import Flask, redirect, url_for, request, render_template
app = Flask(__name__)
#app.route('/success/<name>')
def success(name):
return 'welcome %s' % name
#app.route('/',methods = ['POST', 'GET'])
def login():
if request.method == 'POST':
user = request.form['nm']
return redirect(url_for('success',name = user))
else:
user = request.args.get('nm')
return redirect(url_for('success',name = user))
return render_template('login.html')
if __name__ == '__main__':
app.run(debug = True)
login.html that contains a simple form with the
<html>
<body>
<form action = "http://localhost:5000/login" method = "post">
<p>Enter Name:</p>
<p><input type = "text" name = "nm" /></p>
<p><input type = "submit" value = "submit" /></p>
</form>
</body>
</html>
Your /login route is not mapped to any handler.
Rather login() is attached to / route which when accessed (GET request) doesn't contain nm in request.args and therefore your user variable is set to None.
from flask import Flask, redirect, url_for, request, render_template
app = Flask(__name__)
#app.route('/success/<name>')
def success(name):
return 'welcome %s' % name
#app.route('/login',methods = ['POST', 'GET'])
def login():
if request.method == 'POST':
user = request.form['nm']
return redirect(url_for('success',name = user))
else:
user = request.args.get('nm')
return redirect(url_for('success',name = user))
#app.route('/')
def index():
# Assuming template is available
return render_template('login.html')
if __name__ == '__main__':
app.run(debug = True)

radio buttons and webapp2

Below is the form in quiz.html file.
I don't know how to get the value from a clicked button after submitting the form and writing in /testform.
<html>
<form method="post" action="/testform">
Q1. where are you from?<br>
<input type = "radio" name = "q_1" value ="a">Iraklio</br>
<input type = "radio" name = "q_1" value = "b">Patra</br>
<input type = "radio" name = "q_1" value = "c">Athens</br>
<input type = "submit" value = "submit" >
</form>
</html>
Python script:
import webapp2
import jinja2
templateLoader = jinja2.FileSystemLoader( searchpath="./")
templateEnv = jinja2.Environment( loader=templateLoader )
class quiz(webapp2.RequestHandler):
def get(self):
TEMPLATE_FILE = "quiz.html"
template = templateEnv.get_template( TEMPLATE_FILE )
x = template.render()
self.response.write(x)
class test(webapp2.RequestHandler):
def post(self):
ans = self.request.get('value')
print ans
self.response.write(ans)
app = webapp2.WSGIApplication([('/',quiz),('/testform',test)]
,debug = True)
def main():
from paste import httpserver
httpserver.serve(app, host='127.0.0.1', port='8080')
if __name__ == '__main__':
main()
My objective was:
to print in a subpage (/testform) the letter of the clicked button after submitting the post form.
My mistake was that in : ans = self.request.get('value') , i had to replace 'value' with 'q_1'.Then it worked fine.!!
p.s. https://webapp2.readthedocs.io/en/latest/guide/request.html

Categories

Resources