flask-sqlalchemy foreignkey populating table with null - python

I'm trying to implement a foreign key at one of my tables in flask-sqlalchemy, but keep getting this error all the time:
sqlalchemy.exc.IntegrityError: (psycopg2.errors.NotNullViolation) null value in column "user_id" of relation "applications" violates not-null constraint DETAIL: Failing row contains (3, Company ABC, Software Engineer, New York, NY, USA, Applied, , 2022-09-09, null).
Here is the code:
from flask_login import UserMixin
from database.database import db
class User(UserMixin, db.Model):
__tablename__ = 'users'
id = db.Column(db.Integer, primary_key=True)
email = db.Column(db.String(), nullable=False)
password = db.Column(db.String(), nullable=False)
name = db.Column(db.String(), default='', nullable=True)
application = db.relationship('JobApplicationTracker', lazy=True,backref='author')
def __repr__(self) -> str:
return self.email
def __str__(self) -> str:
return self.email
code:
from database.database import db
class JobApplicationTracker(db.Model):
__tablename__ = 'applications'
id = db.Column(db.Integer, primary_key=True, nullable=False)
name = db.Column(db.String(), nullable=False)
title = db.Column(db.String(), nullable=False)
location = db.Column(db.String(), nullable=False)
status = db.Column(db.String(), nullable=False)
notes = db.Column(db.String(), default='', nullable=True)
date_applied = db.Column(db.String(), nullable=False)
user_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False)
def __repr__(self):
return f'{self.title} at {self.name}'
def __str__(self):
return f'{self.title} at {self.name}'
I have an "applications" table and a "users" table.

The issue is because you have set nullable=False for user_id column in your JobApplicationTracker model but when trying to add, you are passing null value for user_id.
You can try creating a user, pass that user id and things should work fine.
If you want it to work without user id, trying having nullable=true. Again, changing it in the model won't get reflected in the table. You might have to manually change it in the database

Related

sqlalchemy InvalidRequestError

I'm using flask-sqlalchemy, this is not the first relations that i've built, but for some reason it gives me an error when i start flask:
sqlalchemy.exc.InvalidRequestError: One or more mappers failed to initialize - can't proceed with initialization of other mappers. Triggering mapper: 'mapped class User->users'. Original exception was: 'Table' object has no attribute 'sender_id'
These are two models that i'm trying to connect via ForeignKeys:
User:
class User(UserMixin, db.Model):
__tablename__ = 'users'
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(64), index=True, unique=True)
email = db.Column(db.String(120), index=True, unique=True)
password_hash = db.Column(db.String(128))
about_me = db.Column(db.String(140))
last_seen = db.Column(db.DateTime, default=datetime.utcnow)
#relations
posts = db.relationship('Post', back_populates='author', lazy='dynamic')
messages_sent = db.relationship('Message', foreign_keys='messages.sender_id',
back_populates='author', lazy='dynamic')
messages_received = db.relationship('Message', foreign_keys='messages.recipient_id',
back_populates='recipient', lazy='dynamic')
last_message_read_time = db.Column(db.DateTime)
followed = db.relationship(
'User', secondary=followers,
primaryjoin=(followers.c.follower_id == id),
secondaryjoin=(followers.c.followed_id == id),
backref=db.backref('followers', lazy='dynamic'), lazy='dynamic')
def __repr__(self):
return '<User {}>'.format(self.username)
And Messsage:
class Message(db.Model):
__tablename__ = 'messages'
id = db.Column(db.Integer, primary_key=True)
sender_id = db.Column(db.Integer, db.ForeignKey('users.id'))
recipient_id = db.Column(db.Integer, db.ForeignKey('users.id'))
body = db.Column(db.String(140))
timestamp = db.Column(db.DateTime, index=True, default=datetime.utcnow)
#relations
author = db.relationship('User', back_populates='messages_sent', lazy='dynamic')
recipient = db.relationship('User', back_populates='messages_received', lazy='dynamic')
def __repr__(self):
return '<Message {}>'.format(self.body)
I've checked the database itself and it certainly has sender_id in the correct table, tried to change "foreign_keys" parameter to directly name of model Message.sender... Tried to change parameters of lazy on those relations. It still gives me same error.
This is subtle but messages in this case is a table so columns are referenced off of c, like messages.c.sender_id. To use the column of the model class (the mapped class) you would do Message.sender_id.
So...
messages_sent = db.relationship('Message', foreign_keys='messages.c.sender_id',
back_populates='author', lazy='dynamic')
# OR
messages_sent = db.relationship('Message', foreign_keys='Message.sender_id',
back_populates='author', lazy='dynamic')
There is some information here but it doesn't explain the table vs class situation: handling-multiple-join-paths I think I would just use ORM style references until you are more comfortable and then you could use table references if needed.

Flask Rest API SQLAlchemy foreign key error

I got SQLALchemy error, when I tried "flask db migrate"
NoReferencedTableError: Foreign key associated with column 'user.menu_id' could not find table 'menu' with which to generate a foreign key to target column 'id
Menu table
class Menu(db.Model):
__tablename__ = 'menus'
id = db.Column(db.Integer(), primary_key=True)
name = db.Column(db.String(64), index=True, unique=True)
price = db.Column(db.String(64), index=True, unique=True)
description = db.Column(db.String(64), index=True, unique=True)
picture = db.Column(db.String(64), index=True, unique=True)
create_date = db.Column(db.DateTime, default=datetime.utcnow)
users = db.relationship('User', backref="menu", lazy=True)
User table
class User(Model):
""" User model for storing user related data """
id = Column(db.Integer, primary_key=True)
email = Column(db.String(64), unique=True, index=True)
username = Column(db.String(15), unique=True, index=True)
name = Column(db.String(64))
password_hash = Column(db.String(128))
admin = Column(db.Boolean, default=False)
joined_date = Column(db.DateTime, default=datetime.utcnow)
userdataset = db.relationship("Dataset", backref="user", lazy="dynamic")
menu_id = Column(db.Integer(), db.ForeignKey('menu.id'), nullable=False)
def __init__(self, **kwargs):
super(User, self).__init__(**kwargs)
How can ı solve this problem? Where am i doing wrong?
You have renamed your 'Menu' table to 'menus' with this __tablename__ property in your 'Menu' model:
__tablename__ = 'menus'
You then try to reference to the 'Menu' table, when in fact, its name has been changed to 'menus'. The simplest way to solve this would be to change your User.menu_id column to this:
menu_id = Column(db.Integer(), db.ForeignKey('menus.id'), nullable=False)
Another way of fixing this issue would be modifying the __tablename__ property to 'menu'. (You could also just delete it.)

I have a confusion using backref in Flask SQLAlchemy database tables

models.py
#login_manager.user_loader
def load_user(username):
return User.query.get(username)
class User(db.Model,UserMixin):
__tablename__ = 'user_accounts'
id = db.Column(db.Integer,primary_key=True)
username = db.Column(db.String(50),unique=True, nullable=False)
email = db.Column(db.String(120), unique=True, nullable=False)
image_file = db.Column(db.String(20),default='default.jpg')
password = db.Column(db.String(80), nullable=False)
task = db.relationship('Tasks', backref='author', lazy=True)
def __repr__(self):
return f'User <{self.id}> {self.username}'
class Tasks(db.Model):
__tablename__ = 'tasks'
id = db.Column(db.Integer,primary_key=True)
title = db.Column(db.String(100),nullable=False)
content = db.Column(db.Text)
user = db.Column(db.String(50),db.ForeignKey('user_accounts.username'),nullable=False)
date_created = db.Column(db.DateTime, default=datetime.datetime.utcnow,nullable=False)
completed = db.Column(db.Boolean,default=False,nullable=False)
def __repr__(self):
return f'{self.title} by {self.user} ({self.date_created})'
Error:
sqlalchemy.exc.NoReferencedTableError: Foreign key associated with column 'tasks.author' could not find table 'user' with which to generate a foreign key to target column 'username'
Here I have a problem that when I trying to run db.create_all() in terminal I am getting the above error message. I am a bit confused in the usage of backref for db.relationship as my target is to represent a user could have specific task and a task is owned by that user so may I ask how could I properly organize the relationship between two tables in order to create a table with no error messages?

flask admin one to one inline_models

i have those 2 models:
#derive_schema
class Organization(db.Model):
id = Column(UUID(as_uuid=True), unique=True, primary_key=True, server_default=sqlalchemy.text("uuid_generate_v4()"))
name = Column(String, nullable=False, unique=True)
code = Column(String, nullable=False, unique=True)
owner_email = Column(String, nullable=False)
labels = Column(JSONB)
status = Column(Enum(OrganizationStatus), nullable=False)
logo_url = Column(String)
configuration = Column(JSONB, nullable=False)
def __repr__(self):
return self.name
#derive_schema
class PortalSettings(db.Model):
id = Column(UUID(as_uuid=True), unique=True, primary_key=True, server_default=sqlalchemy.text("uuid_generate_v4()"))
organization_id = db.Column(UUID(as_uuid=True), ForeignKey('organization.id'), nullable=False)
portal_settings = Column(JSONB)
organization = relationship(Organization, backref=backref('portal_settings', uselist=False, lazy="joined"))
def __repr__(self):
return self.portal_settings
and this ModelView
class OrganizationView(ConfigurationModelView):
inline_models = (PortalSettings,)
the relationship between organization and portal settings should be one to one,
but i dont understand why in flask admin i got this field when i can add as many portal settings as i want instead of just seen a input field with the portal_settings JSONB field
Based on this gist
https://gist.github.com/DrecDroid/398a05e4945805bc09d1
i've created PR onto Flask-Admin repo and maybe soon it will be merged. Anyway, you may copy-paste code from Gist and use it in your project
https://github.com/flask-admin/flask-admin/pull/2091

How do I make two primary keys, in two different tables, unique using flask-sqlalchemy?

So I am working on a forum-like website for discussions using the python framework Flask. I set up a database using SQLite. I defined two tables (classes) and made primary keys for both. However, the primary keys they produce are the same. For example, for the first set of data, the primary key is 1 for both and I can't differentiate between the two sets of data. I can access the first table's data if I need to, but when I try to get the second table's data, it gives me the first tables data again. Is there any way to have two unique primary keys for both or do I have to set up two different databases.
from datetime import datetime
from flaskblog import db, login_manager
from flask_login import UserMixin
#login_manager.user_loader
def load_user(user_id):
return User.query.get(int(user_id))
class User(db.Model, UserMixin):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(20), unique=True, nullable=False)
email = db.Column(db.String(120), unique=True, nullable=False)
image_file = db.Column(db.String(20), nullable=False, default='default.jpg')
password = db.Column(db.String(60), nullable=False)
posts = db.relationship('Post', backref='author', lazy=True)
posts_addmath = db.relationship('PostAddmath', backref='author', lazy=True)
def __repr__(self):
return f"User('{self.username}', '{self.email}', '{self.image_file}')"
class Post(db.Model):
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(100), nullable=False)
date_posted = db.Column(db.DateTime, nullable=False, default=datetime.utcnow)
content = db.Column(db.Text, nullable=False)
user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
def __repr__(self):
return f"Post('{self.title}', '{self.date_posted}')"
class PostAddmath(db.Model):
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(100), nullable=False)
date_posted = db.Column(db.DateTime, nullable=False, default=datetime.utcnow)
content = db.Column(db.Text, nullable=False)
user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
def __repr__(self):
return f"Post('{self.title}', '{self.date_posted}')"
These are the tables in models.py.
id_addmath = db.Column(db.Integer, primary_key=True)
I tried changing the 'id' variable in the 'PostAddmath' class but that didn't work.
#app.route("/post/<int:post_id>")
#login_required
def post_intmath(post_id):
post = Post.query.get_or_404(post_id)
return render_template('subjects/intmath/post_intmath.html', title=post.title, post=post)
#app.route("/post/<int:post_id>")
#login_required
def post_addmath(post_id):
post = PostAddmath.query.get_or_404(post_id)
return render_template('subjects/addmath/post_addmath.html', title=post.title, post=post)
This is how a access the data in my routes.py.
When I try to access the data using 'post.id' it gives me only the first tables results not the send tables.
If I have to set up a different database please let me know how to do so. Any help is greatly appreciated. Thank You.
You have the same route to both post_intmath and to post_addmath you have to change the routes for example the first route keep it as it is /post/<int:post_id> and the second route change it to /addpost/<int:post_id> for example.

Categories

Resources