These are my User and Role models:
class User(db.Model, UserMixin):
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
firstname = db.Column(db.String(100), nullable=False, server_default='')
lastname = db.Column(db.String(100), nullable=False, server_default='')
username = db.Column(db.String(80), unique=True, nullable=False)
email = db.Column(db.String(80), unique=True, nullable=False)
password = db.Column(db.String(200), nullable=False)
answers = db.relationship('Answer', backref="examinee", lazy=True)
date_created = db.Column(db.DateTime, default=datetime.utcnow)
active = db.Column('is_active', db.Boolean(), nullable=False, server_default='0')
roles = db.relationship('Role', secondary='user_roles', backref=db.backref('users', lazy='dynamic'))
class Role(db.Model, RoleMixin):
id = db.Column(db.Integer(), primary_key=True, autoincrement=True)
name = db.Column(db.String(50), unique=True)
description = db.Column(db.String(255))
class UserRoles(db.Model):
id = db.Column(db.Integer(), primary_key=True, autoincrement=True)
user_id = db.Column(db.Integer(), db.ForeignKey('user.id', ondelete='CASCADE'))
role_id = db.Column(db.Integer(), db.ForeignKey('role.id', ondelete='CASCADE'))
UniqueConstraint('user_id', 'role_id', name='user_role_uniqueness')
How can I remove all users with specific role such as 'student'?
I have tried the following snippet which did not work:
#app.route('/removeAllStudentUsers', methods=['GET', 'POST'])
def remove_all_student_users():
default_role_name = "student"
default_role = Role.query.filter(Role.name == default_role_name).first()
User.query.filter().delete(and_(User.roles.contains(default_role), func.count(User.roles) == 1)) # this line causes the error
db.session.commit()
return redirect(url_for('users'))
The above code causes this error:
sqlalchemy.exc.ArgumentError: Valid strategies for session synchronization are 'evaluate', 'fetch', False
There are multiple issues with your attempt to achieve that, including the fact that you might need a group by in order to check the count of the roles.
I would implement this a following:
_ = (
User.query
.filter(User.roles.any(Role.name == default_role_name)) # 1
.filter(~User.roles.any(Role.name != default_role_name)) # 2
.delete(synchronize_session=False) # 3
)
where:
makes sure to return only those User who has the given role
makes sure to exclude the User who has also other roles (this is what you try to solve with func.count)
this is the solution for the error you get.
Related
AttributeError: 'int' object has no attribute 'username' . I don't know why this happening.
In this return jsonify([{'products':c.products, "user": c.user.username} for c in cart]) c.user.username throws Attribute error.
Code is below
#Views
#app.route('/cart-all')
def show_cart():
user = current_user
cart = Cart.query.filter_by(user=user.id).all()
return jsonify([{'products':c.products, "user": c.user.username} for c in cart])
#Models
class User(db.Model, UserMixin):
id = db.Column(db.Integer(), primary_key=True)
username = db.Column(db.String(length=20), unique=True, nullable=False)
email = db.Column(db.String(length=50), unique=True, nullable=False)
password = db.Column(db.String(length=60), nullable=False)
is_admin = db.Column(db.Boolean, default=False)
cart = db.relationship(
"Cart", cascade="all, delete, delete-orphan", lazy=True
)
class Cart(db.Model):
id = db.Column(db.Integer(), primary_key=True)
user = db.Column(db.Integer(), db.ForeignKey("user.id"), nullable=False)
products = db.Column(db.Integer(), db.ForeignKey("product.id"), nullable=False)
quantity = db.Column(db.Integer())
def __repr__(self):
return self.user.username
The error is how you use and define your user in Cart.
You define it simply as an integer foreign key, so when you try to access c.user.username in show_cart's return, that fails because a int does not have a username attribute.
You define the User's cart as a relationship, why not have a bidirectional relationship ?
Then you can use cart.user as an instance of User.
class User(db.Model, UserMixin):
id = db.Column(db.Integer(), primary_key=True)
username = db.Column(db.String(length=20), unique=True, nullable=False)
email = db.Column(db.String(length=50), unique=True, nullable=False)
password = db.Column(db.String(length=60), nullable=False)
is_admin = db.Column(db.Boolean, default=False)
cart = db.relationship(
"Cart", back_populates="user", cascade="all, delete, delete-orphan", lazy=True
)
class Cart(db.Model):
id = db.Column(db.Integer(), primary_key=True)
user_id = db.Column(db.Integer(), db.ForeignKey("user.id"), nullable=False)
user = relationship("User", back_populates="cart") # add kwargs you need
products = db.Column(db.Integer(), db.ForeignKey("product.id"), nullable=False) # maybe this one is a relationship as well
quantity = db.Column(db.Integer())
def __repr__(self):
return self.user.username
Cannot save record to my db.
I created endpoint which makes user and saves him to db:
#router.post("/user/register/", tags=['user'], status_code=201)
async def user_register_web(user: RegisterWebSchema, db: Session = Depends(get_db)):
if user.password != user.password_repeat:
raise HTTPException(status_code=404, detail="Passwords dont match each other!")
db_user = UserModel(name=user.name.title(), surname=user.surname.title(), email=user.email,
phone_number=user.phone_number, login=user.login, password=user.password,
photo=None, is_admin=False, coins=0)
db.add(db_user)
db.commit()
db.refresh(db_user)
return {"JWT Token": signJWT(user.email),
**user.dict()}
Here is model of my User:
class User(Base):
__tablename__ = "user"
__table_args__ = {'extend_existing': True}
id = Column(Integer, primary_key=True, index=True)
name = Column(String(50), nullable=False)
surname = Column(String(50), nullable=False)
email = Column(String(50), unique=True, nullable=False)
phone_number = Column(String(15), unique=True, nullable=False)
login = Column(String(50), unique=True, nullable=False)
password = Column(String(80), nullable=False)
photo = Column(String(80), nullable=True)
is_admin = Column(Boolean, nullable=False)
coins = Column(Integer, nullable=False)
time_created = Column(DateTime(timezone=True), server_default=func.now())
time_updated = Column(DateTime(timezone=True), onupdate=func.now())
address_id = Column(Integer, ForeignKey("address.id"), nullable=False)
address = relationship("Address", back_populates="user")
pin = relationship("Pin", back_populates="user")
payment_card = relationship("PaymentCard", back_populates="user")
order = relationship("Order", back_populates="user")
feedback = relationship("Feedback", back_populates="user")
post = relationship("Post", back_populates="user")
comment = relationship("Comment", back_populates="user")
animal = relationship("Animal", back_populates="user")
walk = relationship("Walk", back_populates="user")
and here is the error I get:
sqlalchemy.exc.InvalidRequestError: When initializing mapper mapped class Order->order, expression 'Status' failed to locate a name ('Status'). If this is a class name, consider adding this relationship() to the <class 'database.models.OrderModel.Order'> class after both dependent classes have been defined.
model of Order:
class Order(Base):
__tablename__ = "order"
__table_args__ = {'extend_existing': True}
id = Column(Integer, primary_key=True, index=True)
order_code = Column(String(15), nullable=True)
time_created = Column(DateTime(timezone=True), server_default=func.now())
time_updated = Column(DateTime(timezone=True), onupdate=func.now())
status_id = Column(Integer, ForeignKey("status.id"), nullable=False)
status = relationship("Status", back_populates="order")
payment_method_id = Column(Integer, ForeignKey("payment_method.id"), nullable=False)
payment_method = relationship("PaymentMethod", back_populates="order")
user_id = Column(Integer, ForeignKey("user.id"), nullable=False)
user = relationship("User", back_populates="order")
post_office = relationship("PostOffice", back_populates="order")
product = relationship("Product", secondary=OrderProduct, back_populates="order")
and model of Status:
class Status(Base):
__tablename__ = "status"
id = Column(Integer, primary_key=True, index=True)
name = Column(String(100), nullable=False)
time_created = Column(DateTime(timezone=True), server_default=func.now())
time_updated = Column(DateTime(timezone=True), onupdate=func.now())
order = relationship("Order", back_populates="status")
I createrd migration successfully and then db. I dont understand why it shows lack of relationship, which i created. And it appears in lines of codes which dont even use these Tables.
In order to make it work I had to import all of my modules into api file with endpoint. I don't know why but it works right now.
I am beginner trying to make a relational database in Flask project using SQLalchemy
This is the error that I am getting when I try to register a user:-
sqlalchemy.exc.InvalidRequestError: When initializing mapper mapped class Question->question, expression 'Answer' failed to locate a name ('Answer'). If this is a class name, consider adding this relationship() to the <class 'nothingness.models.Question'> class after both dependent classes have been defined.
DB relationships are:-
User (Many to Many) Table
User (1 to Many) Question
Question (1 to Many) Answer
Table (1 to Many) Question
Here are my codes
from datetime import datetime
from nothingness import db
members = db.Table(
"member",
db.Column("id", db.Integer, primary_key=True),
db.Column("table_id", db.Integer, db.ForeignKey("table.id")),
db.Column("user_id", db.Integer, db.ForeignKey("user.id")),
)
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(25), unique=True, nullable=False)
name = db.Column(db.String(25), nullable=False)
email = db.Column(db.String(), unique=True, nullable=False)
image_file = db.Column(db.String(20), nullable=False, default="default.jpg")
password = db.Column(db.String(60), nullable=False)
created_at = db.Column(db.DateTime, nullable=False, default=datetime.utcnow)
member = db.relationship("Table", secondary=members, backref=db.backref("members", lazy=True))
prashna = db.relationship("Question", backref="user", lazy=True)
def __repr__(self):
return f"User('{self.name}', '{self.username}', '{self.email}', '{self.image_file}')db.Model"
class Table(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(25), nullable=False)
key = db.Column(db.String(5), nullable=False)
created_at = db.Column(db.DateTime, nullable=False, default=datetime.utcnow)
question = db.relationship("Question", backref="questions", lazy=True)
def __repr__(self):
return f"Table('{self.id}', '{self.name}', '{self.key}', {self.created_at})"
class Question(db.Model):
id = db.Column(db.Integer, primary_key=True)
question = db.Column(db.String(255), nullable=False)
asked_by = db.Column(db.Integer, db.ForeignKey("user.id"))
asked_to = db.Column(db.Integer, nullable=False)
answer = db.relationship("Answer", backref="question", lazy=True)
table = db.Column(db.Integer, db.ForeignKey("table.id"))
created_at = db.Column(db.DateTime, nullable=False, default=datetime.utcnow)
class Answer:
id = db.Column(db.Integer, primary_key=True)
points = db.Column(db.Integer)
answer = db.Column(db.String(255), nullable=False)
answered_by = db.Column(db.Integer, nullable=False)
table_id = db.Column(db.Integer, nullable=False)
created_at = db.Column(db.DateTime, nullable=False, default=datetime.utcnow)
question = db.Column(db.Integer, db.ForeignKey("question.id"))
def __repr__(self):
return f"Answer('{self.points}', '{self.answer}', '{self.created_at}')"
This error occurred because I forgot to subclass Answer with db.Model
I want this to be able to filter post by the CURRENT USER and delete it. Someone told me to use .WHERE instead of .FILTER but neither of them are working and I get an Attribute Error. How can I get this working?
By the way I am able to delete ALL user post with just db.session.query(Post).delete() but I want it so it only deletes posts for CURRENT_USER.ID (the user that is currently logged into my session)
I added my current models:
#login_required
def delete_all_post():
if current_user.is_authenticated:
db.session.query(Post).delete().filter(Post.user_id == current_user.id)
db.session.commit()
flash('All of your posts has been deleted!', 'success')
return redirect(url_for('main.home'))```
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 User(db.Model, UserMixin):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(16), 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)
delete() return True/ False which is 0 or 1 which is int so you cannot do filter over it
try:
db.session.query(Post).filter(Post.user_id == current_user.id).delete()
I have the following database model:
#login_manager.user_loader
def load_user(id):
return User.query.get(int(id))
class User(db.Model, UserMixin):
id = db.Column(db.Integer, primary_key = True)
username = db.Column(db.String(20), unique=True, nullable=False)
password = db.Column(db.String(30), nullable=False)
email = db.Column(db.String(100), nullable=False, unique=True)
adverts = db.relationship('Advert', backref='autor', lazy=True)
messages_sent = db.relationship('Message',foreign_keys='Message.sender_id', backref='author', lazy='dynamic')
messages_received = db.relationship('Message',foreign_keys='Message.recipient_id', backref='recipient', lazy='dynamic')
telephone = db.Column(db.String(15))
def __repr__(self):
return f"User('{self.username}', '{self.email}'"
class Advert(db.Model):
id = db.Column(db.Integer, primary_key=True)
date = db.Column(db.DateTime, nullable=False, default = datetime.utcnow)
title = db.Column(db.String(100), nullable=False)
content = db.Column(db.Text, nullable = False)
user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
category = db.Column(db.String(50), nullable=False)
price = db.Column(db.Integer)
city = db.Column(db.String(), nullable=False)
messages = db.relationship('Message', backref='messages', lazy=True)
def __repr__(self):
return f"Advert('{self.title}', '{self.date}', '{self.category}')"
class Message(db.Model):
id = db.Column(db.Integer, primary_key=True)
sender_id = db.Column(db.Integer, db.ForeignKey('user.id'))
recipient_id = db.Column(db.Integer, db.ForeignKey('user.id'))
title = db.Column(db.String(100), nullable=False)
body = db.Column(db.String(300), nullable=False)
timestamp = db.Column(db.DateTime, default=datetime.utcnow)
ad_title = db.relationship('Advert', foreign_keys='Advert.title', backref='adtitle', lazy='dynamic')
def __repr__(self):
return f"Message('{self.body}')"
but the relationship between Message and Advert tables doesn't work. I want to do that the every Message have refer to Advert title. Anyone know the solution for this problem?