在 Flask-SQLAlchemy 模型类中使用数据类装饰器?

Cha*_*own 4 python sqlalchemy flask-sqlalchemy python-dataclasses

我编写了一个 Flask-SQLAlchemy 模型类,如下所示(来自此参考):

from flask import Flask
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)
db = SQLAlchemy(app)

class User(db.Model):
    
    __tablename__ = 'user'
    
    user_id = db.Column(db.Integer, primary_key=True)
    user_url = db.Column(db.String(2083), unique=True, nullable=False)
    username = db.Column(db.String(80), unique=True, nullable=False)
    avatar_url = db.Column(db.String(2083), unique=True, nullable=False)
    
    def __init__(self, user_id, user_url, username, avatar_url):
    
        self.user_id = user_id
        self.user_url = user_url
        self.username = username
        self.avatar_url = avatar_url
Run Code Online (Sandbox Code Playgroud)

但是,我想使用dataclass装饰器(参考)来简化其实现,特别是避免重写__init__dunder 方法,并更容易地将此​​类序列化为 Python dict

但是,将此类的实现更改为:

@dataclass
class User(db.Model):

    __tablename__ = 'user'

    user_id: db.Column(db.Integer, primary_key=True)
    user_url: db.Column(db.String(2083), unique=True, nullable=False)
    username: db.Column(db.String(80), unique=True, nullable=False)
    avatar_url: db.Column(db.String(2083), unique=True, nullable=False)
Run Code Online (Sandbox Code Playgroud)

不起作用,产生与此类似的错误(“Mapper 映射类无法为映射表组装任何主键列”)。

db.Model关于如何使用装饰器(或替代解决方案)简化带有基类的类有什么帮助吗dataclass

小智 6

我知道这已经一年多了,但还是为其他为此苦苦挣扎的人回答。

当我多年来一直用 Flask-Marshallow 试图序列化我的 Flask-SqlAlchemy 查询时,我感受到了你的痛苦。

答案是您必须将数据类型放在模型类的顶部。因此,使用OP的示例,您需要更改此设置:

class User(db.Model):
    __tablename__ = 'user'

    user_id: db.Column(db.Integer, primary_key=True)
    user_url: db.Column(db.String(2083), unique=True, nullable=False)
    username: db.Column(db.String(80), unique=True, nullable=False)
    avatar_url: db.Column(db.String(2083), unique=True, nullable=False)
Run Code Online (Sandbox Code Playgroud)

对此:

@dataclass
class User(db.Model):
    __tablename__ = 'user'
    user_id: int
    user_url: str
    username: str
    avatar_url: str

    user_id: db.Column(db.Integer, primary_key=True)
    user_url: db.Column(db.String(2083), unique=True, nullable=False)
    username: db.Column(db.String(80), unique=True, nullable=False)
    avatar_url: db.Column(db.String(2083), unique=True, nullable=False)
Run Code Online (Sandbox Code Playgroud)

请注意,您只需声明需要序列化的字段的数据类型。