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?
Related
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
So i been trying to make a like function for my q&a website. however, i'm stuck on database relations part of the models.py. I'm getting an error that says
"sqlalchemy.exc.InvalidRequestError: One or more mappers failed to initialize - can't proceed with initialization of other mappers. Triggering mapper: 'mapped class User->user'. Original exception was: Could not determine join condition between parent/child tables on relationship User.posts - there are multiple foreign key paths linking the tables. Specify the 'foreign_keys' argument, providing a list of those columns which should be counted as containing a foreign key reference to the parent table."
This is my code for the user and post class
class Post(db.Model):
id = db.Column("id", db.Integer, primary_key=True)
title = db.Column("title", db.String(200))
text = db.Column("text", db.String(100))
date = db.Column("date", db.String(50))
#Create Foreign Key
user_id = db.Column(db.Integer, db.ForeignKey("user.id"), nullable=False)
comments = db.relationship("Comment", backref="post", cascade="all, delete-orphan", lazy=True)
recipient_id = db.Column(db.Integer, db.ForeignKey('user.id'))
likes = db.relationship('PostLike', backref='post', lazy='dynamic')
and my user class
class User(db.Model):
id = db.Column("id", db.Integer, primary_key=True)
first_name = db.Column("first_name", db.String(100))
last_name = db.Column("last_name", db.String(100))
email = db.Column("email", db.String(100))
password = db.Column(db.String(255), nullable=False)
registered_on = db.Column(db.DateTime, nullable=False)
posts = db.relationship("Post", backref="user", lazy=True)
comments = db.relationship("Comment", backref="user", lazy=True)
liked = db.relationship(
'PostLike',
foreign_keys='PostLike.user_id',
backref='user', lazy='dynamic'
)
def like_post(self, post):
if not self.has_liked_post(post):
like = PostLike(user_id=self.id, post_id=post.id)
db.session.add(like)
def unlike_post(self, post):
if self.has_liked_post(post):
PostLike.query.filter_by(
user_id=self.id,
post_id=post.id).delete()
def has_liked_post(self, post):
return PostLike.query.filter(
PostLike.user_id == self.id,
PostLike.post_id == post.id).count() > 0
my postlike class in the models.py
class PostLike(db.Model):
__tablename__ = 'post_like'
id = db.Column(db.Integer, primary_key=True)
user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
post_id = db.Column(db.Integer, db.ForeignKey('post.id'))
my flask file for like_action function
#app.route('/like/<int:post_id>/<action>')
def like_action(post_id, action):
post = Post.query.filter_by(id=post_id).first_or_404()
if action == 'like':
session['user_id'].like_post(post)
db.session.commit()
if action == 'unlike':
session['user_id'].unlike_post(post)
db.session.commit()
return redirect(request.referrer)
You have two foreign keys pointing to User on Post:
user_id = db.Column(db.Integer, db.ForeignKey("user.id"), nullable=False)
recipient_id = db.Column(db.Integer, db.ForeignKey('user.id'))
so, your User doesn't know where to point
posts = db.relationship("Post", backref="user", lazy=True)
Have something like recipient = db.relationship (..) and author = db.relationship (..) in User model, and make posts = db.relationship("Post", back_populates="author", lazy=True).
I want to create database, that consist user info(sqlite db)
class User(db.Model, UserMixin):
id = db.Column(db.Integer, primary_key=True)
login = db.Column(db.String(10), unique = True)
email = db.Column(db.String(20), unique = True)
psw = db.Column(db.String(500), nullable=True)
def __repr__(self):
return f"<User {self.id}>"
This is what i already did.
I want to create fields upcoming_friends, incoming_friends, friends, i think that i need to create a new class that will extends user , but I did not find the documentation and don't understand how to do it.
The User table stores the information that you need about a particular user. If you want to find out what friends this user might have in your application, then you can create another table called Friends.
class Friend(db.Model, UserMixin):
id = db.Column(db.Integer, primary_key=True)
upcoming_friends = db.Column(db.String(64), unique = True)
incoming_friends = db.Column(db.String(64), unique = True)
user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
def __repr__(self):
return f"<Friends: {self.id}>"
To create a relationship between these two database structures, we will do as follows:
class User(db.Model, UserMixin):
id = db.Column(db.Integer, primary_key=True)
login = db.Column(db.String(10), unique = True)
email = db.Column(db.String(20), unique = True)
friends = db.relationship('Friend', backref='<give-a-reference>', lazy='dynamic')
def __repr__(self):
return f"<User {self.id}>"
The user_id field was initialized as a foreign key to user.id, which means that it references an id value from the user's table. In this reference the user part is the name of the database table for the model.
There is a bit of inconsistency when it comes to referring to the user table in db.ForeignKey. Here, you can see that the user table starts with a lower case, whereas when it comes to referencing Friend table in db.relationship we begin with an upper case.
I am trying to add an user to the database file but i get the following error when trying to create an User object:
sqlalchemy.exc.InvalidRequestError: One or more mappers failed to initialize - can't proceed with initialization of other mappers. Triggering mapper: 'mapped class Patient->patient'. Original exception was: Could not determine join condition between parent/child tables on relationship Patient.documents - there are no foreign keys linking these tables. Ensure that referencing columns are associated with a ForeignKey or ForeignKeyConstraint, or specify a 'primaryjoin' expression.
from flask import Flask, render_template, flash
from flask_sqlalchemy import SQLAlchemy
from forms import LoginForm
app = Flask(__name__)
app.config['SECRET_KEY'] = 'SECRETKEY'
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///storage.db'
db = SQLAlchemy(app)
"""
Users
"""
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String)
username = db.Column(db.String, unique=True, nullable=False)
password = db.Column(db.String, nullable=False)
mail = db.Column(db.String, default='test#mail')
role = db.Column(db.Integer)
def __repr__(self):
return f"User('{self.username}', '{self.name}')"
"""
Patients
"""
class Patient(db.Model):
id = db.Column(db.Integer, primary_key=True)
prename = db.Column(db.String, nullable=False)
name = db.Column(db.String, nullable=False)
mail = db.Column(db.String, default='test#mail')
birthdate = db.Column(db.String, nullable=False)
documents = db.relationship('Doc', backref='patient', lazy=True)
def __repr__(self):
return f"Patient('{self.prename}', '{self.name}')"
"""
Documents
"""
class Doc(db.Model):
from datetime import datetime
pdfid = db.Column(db.Integer, primary_key=True)
path = db.Column(db.String)
created = db.Column(db.DateTime, nullable=False, default=datetime.utcnow)
deletetime = db.Column(db.Integer, nullable=False)
patientid = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
def __repr__(self):
return f"Docs('{self.path}', '{self.created}')"
My Steps in a python Terminal (the file is called index):
from index import db
db.create_all()
from index import User, Doc, Patient
user1 = User(name='Test User', username='test', password='testtest', role=1)
When I try step 4 I get the above described error.
I don't see any problem in my code so I would appreciate any help :)
I'm developing a web app with python and flask. I use Flask, SQLAlchemy and PostgreSQL for development. I have many-to-one related models. By this models one company can have many users but each user can only have one company.
models.py
class Company(ResourceMixin, db.Model):
__tablename__ = 'companies'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(100), unique=True, index=True,
nullable=False, server_default='')
phone = db.Column(db.String(24))
email = db.Column(db.String(255), index=True)
address = db.Column(db.String(255))
# Relations
users = db.relationship('User', backref='company')
class User(UserMixin, ResourceMixin, db.Model):
__tablename__ = 'users'
id = db.Column(db.Integer, primary_key=True)
# User details
name = db.Column(db.String(50), index=True)
phone = db.Column(db.String(24))
address = db.Column(db.String(255))
email = db.Column(db.String(255), unique=True, index=True, nullable=False,
server_default='')
password = db.Column(db.String(128), nullable=False, server_default='')
# Relations
company_id = db.Column(db.Integer, db.ForeignKey('companies.id',
onupdate='CASCADE',
ondelete='SET NULL'),
index=True)
views.py
app.route('/')
def index():
company = Company.query.get(1)
flash(company.name, company.user_count)
return render_template('index.html')
Error summary: "user_count" attribute is not part of the Company model.
I want to get the number of the users dynamically from Company model. Attribute should count users on each call of the model and serve it on a regular attribute (like company.user_count). I made it by creating a class method and calling it in view function but i want it to make the process automatic without calling method prior to use attribute.
I tried init function like this:
def __init__(self):
self.user_count = len(self.users)
And like this:
def __init__(self):
self.status()
def status(self):
self.user_count = len(self.users)
return True
And like this:
def __init__(self):
self.status()
#classmethod
def status(self):
self.user_count = len(self.users)
return True
all three versions throws same error. How can i overcome the problem.
Thanks a lot!
You can use a property:
class User(Base):
...
#property
def user_count(self):
return len(self.users)