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'
Related
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()
I have the following group form
class GroupForm(FlaskForm):
groepsnaam = StringField('groepsnaam', validators=[DataRequired()])
deelnemer1 = StringField('Username', validators=[DataRequired()])
deelnemer2 = StringField('Username2', validators=[DataRequired()])
submit = SubmitField('Submit')
This form is supposed to create a group with two users. I am implementing these groups using a certain message within my groupmessage model shown below
class Groupmessage(db.Model):
id = db.Column(db.Integer, primary_key=True)
body = db.Column(db.String(140))
timestamp = db.Column(db.DateTime, index=True, default=datetime.now)
verstuurder = db.Column(db.Integer, db.ForeignKey('user.id'))
group = db.Column(db.String(140), db.ForeignKey('group.id'))
def __repr__(self):
return '<Groupmessage {}>'.format(self.body)
I have combined these two using the following route
#app.route('/groups', methods=['GET', 'POST'])
#login_required
def GroupsPage():
form = GroupForm()
if form.validate_on_submit():
Groupmsg1 = Groupmessage(verstuurder=current_user, group=form.groepsnaam.data,
body="Ik ben de groep binnengetreden")
Groupmsg2 = Groupmessage(verstuurder=form.deelnemer1.data, group=form.groepsnaam.data,
body="Ik ben de groep binnengetreden")
Groupmsg3 = Groupmessage(verstuurder=form.deelnemer2.data, group=form.groepsnaam.data,
body="Ik ben de groep binnengetreden")
db.session.add(Groupmsg1)
db.session.add(Groupmsg2)
db.session.add(Groupmsg3)
db.session.commit()
flash('The group is created!')
return render_template('groups.html', form=form)
Upon submitting the form I get a wall of errors the most significant being
sqlite3.InterfaceError: Error binding parameter 2 - probably unsupported type.
To be frank I do not know why paramater 2 is of an unsupported type, this is referring to the static setting of the body but I can't seem to find a way to fix it, any help would be greatly appreciated.
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'))
I have models:
class Post(db.Model):
id = db.Column(db.Integer, primary_key = True)
body = db.Column(db.String(2000))
user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
comments = db.relationship('Comment', backref='parent_post', lazy='dynamic')
class Comment(db.Model):
id = db.Column(db.Integer, primary_key = True)
body = db.Column(db.String(140))
post_id = db.Column(db.Integer, db.ForeignKey('post.id'))
When entering a post to database I do this:
if form.validate_on_submit():
post = Post(body=form.post.data, author=g.user)
db.session.add(post)
db.session.commit()
This is working right.
But how can I enter a comment to database if I want to pass the 'post.id' value directly
instead of object 'post'. (Not able to 'pass' object via form in html)
if form.validate_on_submit():
comment = Comment(body=form.post.data, parent_post=form.p_id.data)
db.session.add(comment)
db.session.commit()
currently p_id holds value post.id and it gives me error:
AttributeError: 'int' object has no attribute '_sa_instance_state'
Comment.parent_post is a relationship, backed by the integer column Comment.post_id. Currently, you are trying to assign an int (from form.p_id) too the relationship. Assign an int to the column or a Post instance to the relationship.
comment = Comment(post_id=form.p_id.data, body=form.post.data)
# or
post = Post.query.get_or_404(form.p_id.data)
comment = Comment(parent_post=post, body=form.post.data)
The second way is preferable, because you validate that a post with the id exists before trying to use the id.
if form.validate_on_submit():
comment = Comment(body=form.post.data, parent_post=form.p_id.data)
### you need to add `comment` instead `post` in the line below
db.session.add(comment)
db.session.commit()
I strongly think that an error was because of the db.session.add(post). Please the line db.session.add(post) with db.session.add(comment) while adding the comments.
Please make sure that POST-ID that being passed through the form is existing in the post table.
I'm trying out Flask but I'm having the error sqlalchemy.exc.InterfaceError: <unprintable InterfaceError object> while submitting a wtforms. The model class is:
class Post(db.Model):
__tablename__ = 'blog_posts'
id = db.Column(db.Integer, unique=True, primary_key=True)
title = db.Column(db.String(50), unique=False)
content = db.Column(db.Text, unique=False)
user_id = db.Column(db.String, db.ForeignKey('users.username'))
#staticmethod
def post_new_entry(title, content, user_id):
""" Post new entry to database """
new_post = Post(title=title, content=content, user_id=user_id)
db.session.add(new_post)
db.session.commit()
return new_post
def __repr__(self):
return 'PostID {}: {} by {}'.format(self.id, self.title, self.user_id)
For my Form, I have the following:
class PostForm(Form):
title = StringField('Title', validators=[DataRequired(), Length(10, 65)])
post_content = TextAreaField('Content', validators=[DataRequired(), Length(50, 500)])
submit = SubmitField('Publish Post')
The route is:
#main.route('/new_post/', methods=['GET', 'POST'])
#login_required
def add_post():
form = PostForm()
if form.validate_on_submit():
Post.post_new_entry(title=form.title.data,
content=form.post_content.data,
user_id=current_user)
flash("Amazing stuff! Thanks for your submission.")
return redirect(url_for('main.index'))
return render_template('single.html', form=form)
On my html, I'm importing the wtf.html page of the flask-bootstrap:
{{ wtf.quick_form(form) }}
The form shows right but I get the above error on form submission. Any tip or idea on how to proceed would be helpful.
Under def add_post() you write user_id=current_user, but that's not right.
Since you defined for class Post:
user_id = db.Column(db.String, db.ForeignKey('users.username'))
in def add_post() you should use user_id=current_user.username.
In your table class definition you need to add one more line to complete the foreign key relationship.
class Post(db.Model):
__tablename__ = 'blog_posts'
id = db.Column(db.Integer, unique=True, primary_key=True)
title = db.Column(db.String(50), unique=False)
content = db.Column(db.Text, unique=False)
user_id = db.Column(db.String, db.ForeignKey('users.username'))
# Setup the relationship to the User table
users = db.relationship(User)
I was having the same error message in an app which was working one day then not the next. Drove me nuts, the solution was that I had removed a relationship() somewhere.
I have received a similar message when writing data from my application to a database. This is due to the fact that the data that is written from the application needs to have the same format as a defined in the database a db.Column(db.String()) data type cannot have a list as input for example, or any other form.data. You need to use ``str()``` in these cases to prevent this error.
I think your problem came from this area:
Post.post_new_entry(title=form.title.data, content=form.post_content.data, user_id=current_user)
Try to be specific and do it this way:
Post.post_new_entry(title=form.title.data, content=form.post_content.data, user_id=current_user.id)