我编写了一个 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
但是,我想使用
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)
则不会工作,产生类似于 this 的错误(“Mapper 映射类无法为映射表组装任何主键列”)。
有关如何使用基类简化类的任何帮助
db.Model
通过使用
dataclass
装饰器(或替代解决方案)?
使用数据类和 SQLAlchemy 的模型类会导致问题,因为它们都定义了特殊方法
__init__
。数据类的
__init__
方法负责初始化数据类字段,而 SQLAlchemy 的
__init__
方法则负责设置 SQLAlchemy 内部结构。
解决这个问题的方法是在数据类中定义一个自定义
__post_init__
方法,该方法会在数据类的
__init__
方法之后被调用。在
__post_init__
方法中,你可以访问数据类字段的值,并使用这些值初始化 SQLAlchemy 列。
以下是如何在 Flask-SQLAlchemy 模型类中使用数据类装饰器的示例:
from dataclasses import dataclass, field
from typing import List
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
db = SQLAlchemy(app)
@dataclass
class User(db.Model):
__tablename__ = 'user'
user_id: int = field(init=False, metadata={'primary_key': True})
user_url: str
username: str
avatar_url: str
def __post_init__(self):
self.user_id = None # SQLAlchemy will autoincrement this
# 示例用法
user = User(user_url='https://example.com/user1',
username='user1',
avatar_url='https://example.com/avatar1.png')
db.session.add(user)
db.session.commit()
在这个例子中:
-
我们使用
field(init=False)
告诉数据类不要初始化user_id
字段。 -
我们在
__post_init__
方法中将self.user_id
设置为None
,这样 SQLAlchemy 就可以自动递增这个值。 - 我们像往常一样使用 SQLAlchemy 的 API 将新用户添加到数据库中。
其他注意事项:
-
当使用数据类时,不需要显式地定义
__tablename__
属性。数据类会自动使用类的名称作为表名。 -
可以使用
field
函数的metadata
参数向 SQLAlchemy 列传递额外的参数,例如unique
和nullable
。 -
如果需要使用 SQLAlchemy 的关系,可以在数据类中使用
relationship
函数。
这个解决方案允许利用数据类的简洁性和 SQLAlchemy 的强大功能。
标签:python,sqlalchemy,flask-sqlalchemy,python-dataclasses From: 67712091