so I'm getting an error that no unique constraint matches given keys for one of my tables. I have two tables: Users and Items, of which we have a many-to-one relationship (many items for one user). I am using Flask-SQLAlchemy to do all of this:
class ItemModel(db.Model):
__tablename__ = 'items'
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(40))
description = db.Column(db.String(80))
price = db.Column(db.Float(precision=2))
emailAddress = db.Column(db.String(40), db.ForeignKey('users.email'))
class UserModel(db.Model):
__tablename__ = 'users'
id = db.Column(db.Integer)
email = db.Column(db.String(40), primary_key=True)
name = db.Column(db.String(40))
last_name = db.Column(db.String(40))
items = db.relationship('ItemModel', lazy="dynamic")
To create the tables, I have this statement in my 'app.py':
#app.before_first_request
def create_database():
print("Creating tables.")
db.create_all()
The error is: no unique constraint matching given keys for referenced table users.
I am not sure where I'm going wrong since I have a foreign key in ItemModel that matches with the primary key in UserModel. Any suggestions/tips are welcome!
Thanks.
I actually got this to work - As Erwin Brandstetter mentioned above, the error occurred because you need to create the user tables first. In my case, I needed to update the user table in terms of the foreign key/primary key relationship on Postgres itself.
For the sake of someone who ends up here but they structured their code differently, say each entity is in it's own file, check your import order before calling the .create_all() method.
Here's how I like to get around the table ordering issue you're having:
table_names = ['users',
'items']
for table in table_names:
t = db.Model.metadata.tables[table]
t.create(bind=engine)
Related
I'm not sure I properly understand how to get the collection part of the one-to-many relationship.
class ProjectReport(db.Model):
__tablename__ = "project_reports"
id = db.Column(UUID, primary_key=True, default=uuid.uuid4)
project_id = db.Column(UUID, db.ForeignKey("projects.id"), nullable=False)
entries = db.relationship("ProducerEntry", backref="project_report", lazy="dynamic")
class ProducerEntry(Entry):
__tablename__ = "producer_entries"
__mapper_args__ = {"polymorphic_identity": "Entry"}
id = db.Column(UUID, db.ForeignKey("entries.id"), primary_key=True)
project_id = db.Column(UUID, db.ForeignKey("projects.id"), nullable=False)
project_report_id = db.Column(UUID, db.ForeignKey("project_reports.id"), nullable=True)
My problem is that I can't just access the entries field.
for entry in self.entries:
do_something(entry)
This returns NotImplementedError
I managed to get the data via hybrid property but that seems a bit of an overkill since already have the relationship, also it'd get a bit complex for further logic later on.
#hybrid_property
def entries(self):
return ProducerEntry.query.filter_by(project_report_id=self.id)
Ab additional information is that the ProjectReport is basically the common columns of the Entry and Project models, and the project_report_id is nullable, because the entries and projects are generated first and then I can generate the project reports from them. This is how I create the reports:
...
project_report = ProjectReport(date_order=entry.date_order, project_id=entry.project.id)
project_report.entries.append(entry)
...
As far as I know I don't have to add the project_report_id to the producer entry after this.
What am I missing here?
Well yeah, that relationship field returns a query, so I simply should have called:
self.entries.all()
Or anything else which is handling a query.
I was trying to get all the tables from the database whose Account=='Given Account'. But I wasn't able to fetch all the tables, only one table is getting fetched. Please help! Thank you!
#app.route('/user_account/', methods=['GET', 'POST'])
def user_account():
account = session['id']
transactions = Transaction.query.filter_by(Account=account).all()
return render_template('user_account.html',transactions=transactions)
You are calling the Transaction model object which will only give you results from the transactions table. If you are looking to return all tables the account is associated with you will need to import and call each object. For example:
orders = Order.query.filter_by(Account=account).all()
This would return all rows of orders that are associated with the account being queried. However this assumes you've set up your database model with relationship configurations. Ie your transaction model refers to the account being queried by with ForeignKey or Relationship:
class Transaction(db.Model):
__tablename__ = 'transactions'
id = db.Column(db.Integer, primary_key=True)
# Relationships.
user_id = db.Column(db.Integer, db.ForeignKey('users.id',
onupdate='CASCADE',
ondelete='CASCADE'),
index=True, nullable=False)
I am using flask-sqlalchemy in order to create a RestAPI. The idea is to store playlists with one or several medias inside it. To link these two, I am using a many-to-many relationship.
Sometimes, a same media will be inserted twice inside a playlist but it fails because the relationship table already has the entry.
class Media(db.Model):
__tablename__ = 'media'
id = db.Column(db.Integer, primary_key=True)
medias = db.Table('media_playlist',
db.Column('media_id', db.Integer, db.ForeignKey('media.id'), primary_key=True),
db.Column('playlist_id', db.Integer, db.ForeignKey('playlist.id'), primary_key=True),
)
class Playlist(db.Model):
__tablename__ = 'playlist'
id = db.Column(db.Integer, primary_key=True)
medias = db.relationship('Media',
secondary=medias,
lazy='subquery',
backref=db.backref('playlists', lazy=True))
The linked error :
UNIQUE constraint failed: media_playlist.media_id, media_playlist.playlist_id
How would you do to store several times the same link ?
Thank you,
Rom
Why are you setting primary_key=True for foreign key columns? SQLAlchemy
Since you are making a column foreign key it means it is going to store multiple times the same value, but when you make it primary key it means it needs to be unique and now you have this error fails UNIQUE constraint. If you want it to be indexed, you do not have to do anything as DB is indexing foreign keys by default.
I have two tables with a foreign key relationship and I am using flask-admin as admin GUI.
In some cases I need to modify the foreign-key. In this case all existing Records of the related table should be updated (with new foreign key). How would you implement this functionality?
I tried the on_model_change function of flask-admin. Although I run into the problem, that I only get the updated key from the function(?) -> (I need the old key to find the existing assessment-records and update them). Additionally I'm not able to commit the new key unless the Assessment records have been updated (foreign key constraint would not be met).
Can I achieve this functionality within the flask-admin GUI?
class Assessment(db.Model):
__tablename__ = "assesment_table"
id = db.Column(db.Integer, primary_key=True)
psr_id = db.Column(db.String(40), db.ForeignKey("psr_object_table.psr_id"))
class Unit(db.Model):
__tablename__ = "units_table"
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(80))
psr_id = db.Column(db.String(40), unique=True)
#needed for Flask-Admin view
class UnitView(ModelView):
def on_model_change(self, form, model, is_created):
#get old_key
#query and update db with new foreign key
#commit everything
Any help is highly appreciated. Thank you
Use database side cascades:
class Assessment(db.Model):
...
psr_id = db.Column(db.String(40), db.ForeignKey("psr_object_table.psr_id",
onupdate="CASCADE"))
I am having some difficulty setting up a one to one relationship between two models in my flask application. I have two models Employeeand `Photo'. An employee has only one photo associated with it and vice-versa.
This is the code that I have in my models.py file:
class Employee(db.Model):
__tablename__ = 'employees'
id = db.Column(db.Integer, primary_key=True)
photo = db.relationship("Photo", uselist=False, back_populates='employees')
class Photo(db.Model):
__tablename__ = 'photos'
id = db.Column(db.Integer, primary_key=True)
employee_id = db.Column(db.Integer, db.ForeignKey('employees.id'))
employee = db.relationship('Photo', back_populates='photo')
I've followed the instruction on the SQL Alchemy documentation found hereSQL Alchemy simple relationships. The error that I keep encountering is shown below:
sqlalchemy.exc.NoForeignKeysError: Could not determine join condition between parent/child tables on relationship Photo.employee
- there are no foreign keys linking these tables.
Ensure that referencing columns are associated with a ForeignKey or ForeignKeyConstraint, or specify a 'primaryjoin' expression.
I clearly specify the foreign key right here employee_id = db.Column(db.Integer, db.ForeignKey('employees.id')) . I'm not sure what I'm doing wrong. Additionally, I was reading the documentation and it doesn't help that uselist, backref, and back_populates are so similar.
Can someone assist me with this? Help would be greatly appreciated.
One to One relationship stack overflow question
backref automatically adds the reverse relationship to the related model. You can pass a db.backref object to it to specify options to the relationship. back_populates tells SQLAlchemy to populate an existing reverse relationship, rather than creating it. uselist tells SQLAlchemy whether the relationship is a list or not, for cases where it can't determine that automatically.
In your example, you need one relationship, with one backref that is a single item.
You have two typos in your code. First, back_populates='employees' should refer to 'employee', which is what you called the property on the related model. Second, employee = relationship('Photo' is pointing at the wrong model, it should relate to Employee.
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
db = SQLAlchemy(app)
db.engine.echo = True
class Photo(db.Model):
id = db.Column(db.Integer, primary_key=True)
class Employee(db.Model):
id = db.Column(db.Integer, primary_key=True)
photo_id = db.Column(db.ForeignKey(Photo.id))
photo = db.relationship(Photo, backref=db.backref('employee', uselist=False))
db.create_all()
db.session.add(Employee(photo=Photo()))
db.session.commit()
print(Employee.query.get(1).photo)