在尝试制作自己的博客应用程序时,我希望我的用户拥有角色,以便不同的用户可以访问我博客的不同部分。为了添加我的角色模型,我按照 https://docs.sqlalchemy.org/en/20/orm/basic_relationships.html#many-to-many 文档创建关联表以及我的角色表。
from datetime import datetime, timezone
from typing import Optional
import sqlalchemy as sa
import sqlalchemy.orm as so
from app import db, login
from werkzeug.security import generate_password_hash, check_password_hash
from flask_login import UserMixin
from flask_security.models import fsqla_v3 as fsqla
from hashlib import md5
roles_user_table = db.Table(
"roles_user_table",
db.metadata,
sa.Column("user_id", sa.Integer, sa.ForeignKey("user.id"), primary_key=True),
sa.Column("roles_id", sa.Integer, sa.ForeignKey("roles.id"), primary_key=True)
)
class User(fsqla.FsUserMixin, db.Model):
id: so.Mapped[int] = so.mapped_column(primary_key=True)
email: so.Mapped[str] = so.mapped_column(sa.String(120), index=True, unique=True)
password_hash: so.Mapped[Optional[str]] = so.mapped_column(sa.String(256))
posts: so.WriteOnlyMapped['Post'] = so.relationship(back_populates='author')
about_me: so.Mapped[Optional[str]] = so.mapped_column(sa.String(140))
last_seen: so.Mapped[Optional[datetime]] = so.mapped_column(default=lambda: datetime.now(timezone.utc))
role: so.Mapped[list['Roles']] = so.relationship("Roles", secondary=roles_user_table,
primaryjoin=(roles_user_table.c.user_id == id),
secondaryjoin=(roles_user_table.c.roles_id == id),
back_populates="name")
def set_password(self, password):
self.password_hash = generate_password_hash(password)
def check_password(self, password):
return check_password_hash(self.password_hash, password)
def __repr__(self):
return '<User {}>'.format(self.email)
def avatar(self, size):
digest = md5(self.email.lower().encode('utf-8')).hexdigest()
return f'https://www.gravatar.com/avatar/{digest}?d=identicon&s={size}'
class Post(db.Model):
id: so.Mapped[int] = so.mapped_column(primary_key=True)
body: so.Mapped[str] = so.mapped_column(sa.String(140))
timestamp: so.Mapped[datetime] = so.mapped_column(index=True, default=lambda: datetime.now(timezone.utc))
user_id: so.Mapped[int] = so.mapped_column(sa.ForeignKey(User.id), index=True)
author: so.Mapped[User] = so.relationship(back_populates='posts')
def __rep__(self):
return '<Post {}>'.format(self.body)
class Roles(db.Model, fsqla.FsRoleMixin):
id: so.Mapped[int] = so.mapped_column(primary_key=True)
name: so.Mapped[User] = so.relationship(secondary=roles_user_table, back_populates="role")
def __rep__(self):
return '<Role {}>'.format(self.name)
当我尝试通过运行命令在角色表中添加角色时:
admin_role = Roles(name="admin")
sqlalchemy.exc.InvalidRequestError: When initializing mapper Mapper[User(user)], expression 'Role' failed to locate a name ('Role'). If this is a class name, consider adding this relationship() to the <class 'app.models.User'> class after both dependent classes have been defined.
我的桌子设置正确吗?或者这个问题是因为其他原因而发生的?
您需要使用单数版本的 Role 作为您的类名。