在我的 Flask 博客应用程序中创建多对多关系表时遇到问题

问题描述 投票:0回答:1

在尝试制作自己的博客应用程序时,我希望我的用户拥有角色,以便不同的用户可以访问我博客的不同部分。为了添加我的角色模型,我按照 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.

我的桌子设置正确吗?或者这个问题是因为其他原因而发生的?

python flask flask-sqlalchemy
1个回答
0
投票

您需要使用单数版本的 Role 作为您的类名。

© www.soinside.com 2019 - 2024. All rights reserved.