Flask SQLAlchemy Add Images - python

I want to add into a sqlalchemy database an image where a user uploads one. I tried to do it with this StackOverFlow [post].(Serve image stored in SQLAlchemy LargeBinary column)
Here is the flask code:
from flask import Flask,render_template,request
from flask_sqlalchemy import SQLAlchemy
from base64 import b64encode
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///users1.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db = SQLAlchemy(app)
class Images(db.Model):
id = db.Column(db.Integer,primary_key=True)
name = db.Column(db.String(200))
img = db.Column(db.LargeBinary)
db.create_all()
mylist = []
#app.route('/',methods=['POST','GET'])
def home():
if request.method == 'POST':
img1 = request.files['ab']
imager = Images(name='abc',img=img1)
db.session.add(imager)
db.session.commit()
return render_template('other.html')
#app.route('/allimg',methods=['POST','GET'])
def home1():
mylist1 = Images.query.filter_by(name='abc').all()
event = Images.query.get_or_404(id)
image = b64encode(event.img)
return render_template('new.html',posts=image)
if __name__ == '__main__':
app.run(debug=True)
Other.html
<form action='' method='post' enctype="multipart/form-data">
<button><input type='file' name='ab' id='file-input' multiple></button>
</form>
New.html
<html>
<body>
{%for i in posts%}
<img src="data:;base64,{{ logo }}"/>
{%endfor%}
</body>
</html>
When I go to allimg (The page that I show all images) I get
sqlalchemy.exc.InterfaceError
sqlalchemy.exc.InterfaceError: (sqlite3.InterfaceError) Error binding parameter 0 - probably unsupported type.
[SQL: SELECT images.id AS images_id, images.name AS images_name, images.img AS images_img
FROM images
WHERE images.id = ?]
[parameters: (<built-in function id>,)]
(Background on this error at: https://sqlalche.me/e/14/rvf5)
Please answer.
Thanks.

Serve image stored in SQLAlchemy LargeBinary
column
#app.route('/event/<int:id>/logo')
def event_logo(id):
event = Event.query.get_or_404(id)
image = b64encode(event.logo)
return render_template('event.html', event=event, logo=image)
id in this context is comming in as an int parameter
your passing in id as (<built-in function id>,)
from here https://docs.python.org/3/library/functions.html#id

Related

Flask TypeError TypeError: a bytes-like object is required, not 'NoneType'

I want to add images into sqlalchemy in flask and I tried to do it from this post.
from flask import Flask,render_template,request,Response
from flask_sqlalchemy import SQLAlchemy
from base64 import b64encode
from werkzeug.utils import secure_filename
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///users1.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db = SQLAlchemy(app)
class Images(db.Model):
id = db.Column(db.Integer,primary_key=True)
name = db.Column(db.Text)
img = db.Column(db.Text)
db.create_all()
mylist = []
#app.route('/',methods=['POST','GET'])
def home():
if request.method == 'POST':
img1 = request.files['ab']
imager = img1.save(secure_filename(img1.filename))
imager = Images(name='abc',img=img1.read())
db.session.add(imager)
db.session.commit()
return render_template('other.html')
#app.route('/allimages',methods=['POST','GET'])
def home1():
mylist1 = Images.query.filter_by(name='abc').all()
for i in mylist1:
image = b64encode(i.img)
return render_template('new.html',posts=image)
if __name__ == '__main__':
app.run(debug=True)
But when I go to allimages I get TypeError TypeError: a bytes-like object is required, not 'NoneType'. What should I do? I get the error in the browser and also in the console.
Thanks.
Looks like you forgot to use the decode method of b64encode.
But also you're overwriting image, each time in the for loop. Going by the linked question you should be adding a new attribute to each image in images, in this case uri_src:
images = Images.query.filter_by(name='abc').all()
for image in images:
image.uri_src = b64encode(image.img).decode('utf-8')
# Now pass images (plural) to the template
return render_template('new.html',posts=images)
Then handle this in the template like:
{% for image in posts %}
<p>Name: {{ image.name }}</p>
<p>Image: </p> <img src="data:;base64,{{ image.uri_src }}">
{% endfor %}

I have a issue about execute in python flask

I am new in build python api. I want to get the data depend on date.
https://programminghistorian.org/en/lessons/creating-apis-with-python-and-flask#what-is-an-api
I am following this link to code my api but I don't know what can I do in execute.
This is my python code:
# -*- coding: utf-8 -*-
from flask import Flask, render_template, request
from flask_mysqldb import MySQL
app = Flask(__name__)
app.config["DEBUG"] = True
app.config['MYSQL_HOST'] = 'localhost'
app.config['MYSQL_USER'] = 'root'
app.config['MYSQL_PASSWORD'] = 'root'
app.config['MYSQL_DB'] = 'MyDB'
app.config['MYSQL_charset'] ='utf8'
mysql = MySQL(app)
#app.route('/',methods = ['GET','POST'])
def index():
if request.method == "POST":
details = request.form
firstday = details['firstday']
lastday = details['lastday']
cur = mysql.connection.cursor()
cur.execute("select * from transaction join transaction_item on transaction.id = transaction_item.transaction_id join customer on customer.id = transaction.customer_id where transaction_datetime <= lastday and transaction_datetime >= firstday VALUES (%s, %s)", (firstday, lastday))
mysql.connection.commit()
cur.close()
return 'success'
return render_template('index.html')
if __name__ == '__main__':
app.run()
This is my HTML code:
<HTML>
<BODY bgcolor="cyan">
<form method="POST" action="">
<center>
<H1>Enter your details </H1> <br>
first_transaction_datetime <input type = "text" name= "firstday" /> <br>
last_transaction_datetime <input type = "text" name= "lastday" /> <br>
<input type = "submit">
</center>
</form>
</BODY>
</HTML>
When you are sending requests to a back-end it does not fill out the form an easy way to do it would be to add the query values in the URL
http://127.0.0.1:5000/?firstName=<firstName>&lastName=<lastName>
then your python code would look something like this.
#app.route('/',methods = ['GET','POST'])
def index():
firstName = request.args.get('firstName')
lastName = request.args.get('lastName')
if request.method == "POST":
# Do stuff here

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()

Flask Application TypeError: __init__() missing 1 required positional argument

I am getting started with Flask and trying to create a simple database web application.
It renders 2 html-templates:
show_all.html which shows the data of a database table
new.html which is a form to insert data in to the table
The show_all.html renders correctly. When I click on the submit-button on the new.html I get the following error message:
TypeError: __init__() takes 1 positional argument but 2 were given
app.py
from flask import Flask, request, flash, url_for, redirect, render_template
from flask_sqlalchemy import SQLAlchemy
import psycopg2
DB_URL = 'postgresql+psycopg2://{user}:{pw}#{url}/{db}'.format(user='*******',pw='******',url='******',db='*****')
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = DB_URL
db = SQLAlchemy(app)
class test (db.Model):
__table_args__ = {"schema":"SaubannerDB"}
id1 = db.Column('id1', db.Integer, primary_key=True)
name1 = db.Column(db.String(10))
def __init__(self, name1, id1):
self.name1 = name1
self.id1 = id1
#app.route('/')
def show_all():
return render_template ('show_all.html', tests=test.query.all())
#app.route('/new', methods=['GET','POST'])
def new():
if request.method == 'POST':
if not request.form['name1'] or not request.form['id1']:
flash ('Please enter all fields')
else:
name1 = test(request.form['name1'])
id1 = test(request.form['id1'])
entry = (name1,id1)
db.session.add(entry)
db.session.commit()
return render_template('new.html')
return render_template('new.html')
app.run(host = '0.0.0.0', port = 5050)
app.debug = True`
The new.html file looks like this:
<!DOCTYPE html>
<html>
<body>
<form method="post" action="/new">
<label for="name1"/label><br>
<input type="text" name="name1" placeholder="name"><br>
<label for="id1"/label><br>
<input type="text" name="id1" placeholder="id"><br>
<input type="submit" value="Submit"><br>
</form>
</body>
</html>`
Can anyone help?
Found it out. The following Code works, note the changes for the variable "entry":
from flask import Flask, request, flash, url_for, redirect, render_template
from flask_sqlalchemy import SQLAlchemy
import psycopg2
DB_URL = 'postgresql+psycopg2://{user}:{pw}#{url}/{db}'.format(user='*******',pw='******',url='******',db='*****')
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = DB_URL
db = SQLAlchemy(app)
class test (db.Model):
__table_args__ = {"schema":"SaubannerDB"}
id1 = db.Column('id1', db.Integer, primary_key=True)
name1 = db.Column(db.String(10))
def __init__(self, name1, id1):
self.name1 = name1
self.id1 = id1
#app.route('/')
def show_all():
return render_template ('show_all.html', tests=test.query.all())
#app.route('/new', methods=['GET','POST'])
def new():
if request.method == 'POST':
if not request.form['name1'] or not request.form['id1']:
flash ('Please enter all fields')
else:
entry = test(request.form['id1'],
request.form['name1'])
db.session.add(entry)
db.session.commit()
return render_template('new.html')
return render_template('new.html')
app.run(host = '0.0.0.0', port = 5050)
app.debug = True
If you look here it seems that the init argument is only in the pre-release version:
https://github.com/teracyhq/flask-classful/releases
If that is the case, they shouldn't have the init_argument in the documentation. It's unprofessional.

Iterate over the results returned from session query in SqlAlchemy and print them in a flask template

How can I iterate over the results returned by session.query from a database and print them in a flask template?
I have the following code where I am able to successfully iterate over the results returned from database and print employees name outside of my flask app.
I am just not able to figure out as how to use the following code and print out the employees name in a flask template:
def getEmployees():
engine = create_engine('mssql+pyodbc://<server name>/<DB name>?driver=SQL+Server+Native+Client+11.0')
Base = declarative_base(engine)
class Bookmarks(Base):
__tablename__ = 'table name'
Employee = Column(String(50))
__table_args__ = {'autoload':True}
def loadSession():
metadata = Base.metadata
Session = sessionmaker(bind=engine)
session = Session()
return session
if __name__ == "__main__":
session = loadSession()
results = Bookmarks.query.filter_by(Manager='Bob')
Route:
#app.route('/employeesName', methods=['GET')
def employeesName():
if request.method == 'GET':
return render_template('getEmployees.html')
Template (getEmployees.html):
<h2>Results</h2>
{% for employees in results %}
{{ employees.Employee }}
{% endfor %}
How can I print employees name filtered by Manager = 'Bob' in the flask template?
Thank you so much!
figured this out.
I was supposed to add function name while rendering the template:
#app.route('/employeesName', methods=['GET')
def employeesName():
if request.method == 'GET':
return render_template('getEmployees.html', results=getEmployees())

Categories

Resources