Fetch two columns from db using SQLalchemy - python

I am learning python and trying to create a drop-down in my form with the data from another table. here is my code
Models.py
class empmasterModel(db.Model):
__tablename__ = "empmaster"
Empnum = db.Column(db.Integer, primary_key=True)
Employee_Number = db.Column(db.Integer(),primary_key=True,unique = True)
Employee_Name = db.Column(db.String())
Employee_Type = db.Column(db.String())
Coreid = db.Column(db.String())
EmailId = db.Column(db.String())
def __init__(self, Employee_Number,Employee_Name,Employee_Type,Coreid,EmailId):
self.Employee_Number = Employee_Number
self.Employee_Name = Employee_Name
self.Employee_Type = Employee_Type
self.Coreid = Coreid
self.EmailId = EmailId
def __repr__(self):
return f"{self.Employee_Number}:{self.Employee_Name}:{self.Employee_Type}:{self.Coreid}:{self.EmailId}"
Above is my models.py code with class empmaster from which DB table I need the employee number and employee name.
app.py
#app.route('/component/add', methods=['GET', 'POST'])
def componentadd():
error_msg = ''
success_msg = ''
if request.method == 'GET':
empmaster_data = empmasterModel.query.all()
print(empmaster_data , "dbbbbbbbbbbbbb")
return render_template('component/add.html', empmaster_data=empmaster_data)
Above is the app.py code where I am trying to fetch data from empmaster table. But here I am getting whole table data but not two-column data. I tried two column names in brackets after the filter too but it did not work. I searched for many solutions but was not getting desired results. Can somebody help me?

If you have session management, you can do something like:
session.query(
empmasterModel.Employee_Number.label("Employee_Number"),
empmasterModel.Employee_Name.label("Employee_Name")
).all()
If you use Flask with no session management, you can get the session from the SQLAlchemy instance.
db = SQLAlchemy() # Usually in you app.py
And then:
db.session.query(
empmasterModel.Employee_Number.label("Employee_Number"),
empmasterModel.Employee_Name.label("Employee_Name")
).all()

Related

Pandas to_sql() table not allowing me to insert new rows

I have code that converts a csv into an sqlalchemy table. When I try and use db.session.add() it creates an entry in the datatable, but the id is null. This stops me from being able to interact with the data. I tried creating a normal SQL alchemy table and was able to insert rows fine, but for whatever reason the way pandas added the table is preventing me from adding more rows to the table. I will attach the relevant code. Let me know if you need more
db = SQLAlchemy()
DB_NAME = "database.db"
app = Flask(__name__)
sslify = SSLify(app)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///test.db'
db.init_app(app)
class Master(db.Model):
__tablename__ = "Master"
__table_args__ = {'extend_existing':True}
index = db.Column(db.Integer, primary_key = True)
username = db.Column(db.String(150))
full_name = db.Column(db.String(150))
serial_number = db.Column(db.String(150))
asset_tag = db.Column(db.Integer)
def __repr__(self):
return '<Comments %r>' % self.id
def __init__(self, username, full_name, serial_number, asset_tag):
self.username = username
self.full_name = full_name
self.serial_number = serial_number
self.asset_tag = asset_tag
file_name = 'master.csv'
df = pd.read_csv(file_name)
df['asset_tag'].fillna('-999', inplace=True)
df['asset_tag'] = df['asset_tag'].astype('int')
df.replace(-999," ",inplace=True)
df.fillna(" ", inplace=True)
df.to_sql(con = app.config['SQLALCHEMY_DATABASE_URI'], index_label='index', name=Master.__tablename__, if_exists='append')
#app.route('/adds', methods = ['GET','POST'])
def adds():
thefullname = request.form.get('add_full')
theuser = request.form.get('add_user')
theasset = request.form.get('add_asset')
theserial = request.form.get('add_serial')
theadd = Master(username = theuser, full_name=thefullname, asset_tag=theasset, serial_number=theserial)
db.session.add(theadd)
db.session.commit()
return render_template('home.html')

Flask SQLAlchemy - Relationship with two models

i am trying to create app which would track all the service incidents.
I have created two models
Printer - Which holds all the information about printer (Inventory number, IP Adress etc)
PrinterService - Which should hold all the data about services.
i am trying to connect those two, so if i fill the form for service - it will join to the Printer table.. but i am failing with this.
This is what i am working with.
Models:
class Printer(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(200))
ip = db.Column(db.String(200))
class PrinterServis(db.Model):
id = db.Column(db.Integer, primary_key=True)
printer_komponent = db.Column(db.String(140))
printer_opis_chyby = db.Column(db.String(140))
printer_id = db.Column(db.Integer, db.ForeignKey('printer.id'))
Forms:
class PrinterForm(FlaskForm):
printer_name = StringField('Názov Tlačiarne', validators=[InputRequired()])
printer_ip = StringField('IP Tlačiarne', validators=[InputRequired()])
class PrinterServisForm(FlaskForm):
printer_komponent = StringField('Vadný komponent', validators=[InputRequired()])
printer_opis_chyby = StringField('Opis Chyby', validators=[InputRequired()])
Views:
#app.route('/')
def index():
printers = Printer.query.all()
return render_template('index.html', printers=printers)
#app.route('/add', methods=['GET', 'POST'])
def add_printer():
form = PrinterForm()
if form.validate_on_submit():
name = form.printer_name.data
ip = form.printer_ip.data
new_printer = Printer(name=name, ip=ip)
db.session.add(new_printer)
db.session.commit()
flash("Pridanie tlačiarne prebehlo úspešne")
return redirect(url_for('index'))
return render_template('add_printer.html', form=form)
#app.route('/printer/<int:printer_id>/', methods=['GET', 'POST'])
def view_printer(printer_id):
form = PrinterServisForm()
printer = Printer.query.get_or_404(printer_id)
if form.validate_on_submit():
printer_komponent = form.printer_komponent.data
printer_opis_chyby = form.printer_opis_chyby.data
printer_servis_id = Printer.query.get_or_404(printer_id)
new_servis = PrinterServis(printer_komponent=printer_komponent, printer_opis_chyby=printer_opis_chyby, printer_id=printer_servis_id)
db.session.add(new_servis)
db.session.commit()
flash("Servis bol objednaný")
return redirect(url_for('index'))
return render_template('printer.html', printer=printer, form=form)
With this i am getting the error
sqlalchemy.exc.InterfaceError: (sqlite3.InterfaceError) Error binding parameter 2 - probably unsupported type.
[SQL: INSERT INTO printer_servis (printer_komponent, printer_opis_chyby, printer_id) VALUES (?, ?, ?)]
[parameters: ('Valec', 'Valec je poškodený, nefunguje', <Printer 1>)]
(Background on this error at: https://sqlalche.me/e/14/rvf5)
probably the issue is that the "printer_id" Value is <Printer 1> instead of 1, but how can i change it?
My head hurts now.. I am only a beginner so sorry for probably stupid question.
Thank you!
Your problem is that your relationship between your two models is not quite complete. You need to add something similar to this to the Printer model to complete the relationship:
printer_service = db.relationship('PrinterServis', backref='printer')
This inserts a relationship 'column' which holds the parent printer, into the PrinterServis table. To correctly create a PrinterServis object, fill this 'printer' attribute instead of the foreign key, 'printer_id'.
new_servis = PrinterServis(..., printer=printer_servis_id)
You could then access this parent printer with something similar to the following:
printer_servis_object = PrinterServis.query.first() #get a valid object
printer_object = printer_servis_object.printer #access its backref of 'printer'

Example of using Python wtform datetime with sqlalchemy and sqlite

I am trying to create a form using wtform datetime that accepts a date with a date picker.
form.py
class RegistrationForm(FlaskForm):
eventname = StringField('Event Name', validators=[DataRequired()])
eventstart = DateField(
'Enter start date and time', id='datepick', validators=[DataRequired()]
)
This renders the date and time picker correctly. However, I am not understanding how to get it into the correct format using sqlalchemy and sqlite. It doesn't seem to be validating on submit. When I add a print(events), the output is {}.
view.py
#events_blueprint.route('/add', methods=['GET', 'POST'])
def register():
form = RegistrationForm()
print(form.errors)
if form.validate_on_submit():
event = Events(
eventname=form.eventname.data,
eventstart=form.eventstart.data,
# eventstop=form.eventstop.data,
)
db.session.add(event)
db.session.commit()
flash("Thank you for registering your event.")
return render_template('add.html', form=form)
class Events(db.Model):
__tablename__ = 'events'
id = db.Column(db.Integer, primary_key=True)
eventname = db.Column(db.Text(64), unique=True, index=True)
eventstart = db.Column(db.Text, nullable=False)
# This is a one-to-many connection with Eventdetails database
details = db.relationship('Eventdetails', backref='event', lazy='dynamic')
def __init__(
self, eventname, eventstart
):
self.eventname = eventname
self.eventstart = eventstart
def __repr__(self):
return f"{self.eventname}"
Any help pointing me in the right direction would be greatly appreciated. Ultimately, I would like to factor in the timezone and event end time so I have a time range.

flask-sqlalchemy: Trouble joining tables from two databases (different bind keys). Getting error 1146 (see below)

I'm building a Flask-Restful API using python and sqlalchemy, and I'm trying to join two tables from different databases. It appears that I'm only able to search for tables in one database at a time. Am I missing something?
from flask_sqlalchemy import SQLAlchemy
from flask import Flask, jsonify, request
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://username:password#host:8000/database1'
app.config['SQLALCHEMY_BINDS'] = {
'database2': 'mysql://username:password#host:8000/database2'
}
db = SQLAlchemy(app)
db.create_all(bind='database2')
class Table1(db.Model):
__tablename__ = "table1"
__table_args__ = {'schema':'database1'}
location_id = db.Column(db.Integer, primary_key=True)
def __init__(self, location_id):
self.location_id = location_id
def __repr__(self):
return '{}'.format(self.location_id)
class Table2(db.Model):
__bind_key__ = "database2"
__tablename__ = "table2"
__table_args__ = {'schema':'database2'}
other_id = db.Column(db.Integer, primary_key=True)
location_id = db.Column(db.Integer, db.ForeignKey('database1.table1.location_id'))
def __init__(self, other_id, location_id):
self.other_id = other_id
self.location_id = location_id
def __repr__(self):
return '{}'.format(self.other_id)
#app.route('/', methods=['GET'])
def returnRes():
session = db.session
q = session.query(table1).join(table2, table1.location_id==table2.location_id).all()
return str(q)
In my browser, I am getting the error:
'sqlalchemy.exc.ProgrammingError: (_mysql_exceptions.ProgrammingError) (1146, "Table 'database1.table2' doesn't exist").
Both tables indeed exist, as when I change my query to
q = session.query(table2).join(table1, table2.location_id==table1.location_id).all()
I get an error that database2.table1 doesn't exist.
I'm using python==3.6.1, Flask==0.11.1 and Flask-SQLAlchemy==2.1
Adding a data base schema argument to my table classes and adding a foreign key fixed this problem. I found the answer at this link: https://github.com/mitsuhiko/flask-sqlalchemy/issues/172
I've updated the question to reflect the answer in case it helps anyone else.
I'm not sure if the binds are redundant, but I've left them in because they don't seem to interfere with anything.
You need to add Schema declarations. It is strange that Flask-SQLAlchemy doesn't mention this at all in their documentation.
The Foreign Keys are unnecessary for this to work.
class Table1(db.Model):
__tablename__ = "table1"
__table_args__ = {'schema':'database1'}
#...
def __init__(self, location_id):
self.location_id = location_id
def __repr__(self):
return '{}'.format(self.location_id)
class Table2(db.Model):
__bind_key__ = "database2"
__tablename__ = "table2"
__table_args__ = {'schema':'database2'}
#...
so long as your config file looks like this
SQLALCHEMY_DATABASE_URI = 'postgres:////path/to/database1'
SQLALCHEMY_BINDS = {
'database2': 'mysqldb:////path/to/database2'
}

Error in One to Many SQLAlchemy database with Flask

I am currently trying to insert items into my database. I am using SQLlite and SQLAlchemy with Flask but there seems to be an issue. Whenever I try to insert items manually from the cmd, I receive an error.
This session's transaction has been rolled back due to a previous
exception during flush.
I have implemented an one to many relationship in my database but something seems to keep messing up. Here is my Python code:
from flask import Flask, render_template, request, redirect, url_for
from flask_sqlalchemy import SQLAlchemy
from flask_bootstrap import Bootstrap
main = Flask(__name__)
db = SQLAlchemy(main)
main.config['SQLALCHEMY_DATABASE_URI'] = 'postgresql://YYYYYYY:XXXXXXX#localhost/address'
main.config['SECRET_KEY'] = 'something-secret'
Bootstrap(main)
class Organisation(db.Model):
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(80), unique=True)
email = db.Column(db.String(40), unique=True)
number = db.Column(db.String(40), unique=True)
employees = db.relationship('Person', backref='employer', lazy='dynamic')
def __init__(self, title, email, number):
self.title = title
self.email = email
self.number = number
class Person(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(60), unique=False)
email = db.Column(db.String(40), unique=True)
mobile = db.Column(db.String(40), unique=True)
employer_id = db.Column(db.Integer, db.ForeignKey('organisation.id'))
def __init__(self, name, email, mobile, employer_id):
self.name = name
self.email = email
self.mobile = mobile
self.employer_id = employer_id
#main.route('/', methods=['GET'])
def index():
result = Person.query.all()
org_result = Organisation.query.all()
return render_template("index.html", result=result, org_result=org_result)
#main.route('/additems', methods=['GET'])
def additems():
return render_template('add.html')
#main.route('/add', methods=['GET', 'POST'])
def add():
person = Person(request.form['name'], request.form['email'], request.form['mobile'])
db.session.add(person)
db.session.commit()
if __name__ == "__main__":
main.run(debug=True)
If I have to honest, I think that my issue is somewhere in the init functions. I have tried changing them in several ways:
1.Adding employees as self.employees = employees and trying directly to input an Organisation as:
organisation_one=Organisation(title="XX",email="xx#mail.com",number="3838",employees=person_one) but it fired back an error even before I could submit person_one
2.I have tried referencing the employer_id in the Person __init__ file and when I try to add the organisation id, I recive an error "can't adapt type".
What am I doing wrong with the one to many database model? Can someone help me out?
Your database models require a __tablename__ attribute like this: This tells it what the actual table name is in the database. Otherwise SQLAlchemy doesn't know how to write the SQL for you.
class Organisation(db.Model):
__tablename__ = 'organisation'
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(80), unique=True)
email = db.Column(db.String(40), unique=True)
number = db.Column(db.String(40), unique=True)
employees = db.relationship('Person', backref='employer', lazy='dynamic')
def __init__(self, title, email, number):
self.title = title
self.email = email
self.number = number
You must also reference this table name in the backref for your Person model:
db.ForeignKey('organisation.id')) # assuming "organisation" is the table name
Also, your /add route is incomplete and will result in an error:
#main.route('/add', methods=['GET', 'POST'])
def add():
person = Person(request.form['name'], request.form['email'], request.form['mobile'])
db.session.add(person)
db.session.commit()
# e.g. add some instruction here on what to do...
flash('Person %s <%s>added!' % (request.form['name'], request.form['email']))
return redirect(url_for('main.additems'))

Categories