首页 > 编程问答 >在 Flask-SQLAlchemy 模型类中使用数据类装饰器?

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

时间:2024-07-24 11:31:58浏览次数:14  
标签: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

但是,我想使用 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

相关文章

  • Python实现excel数据的读取和写入
    1.安装说到前面的话,实现excel文件数据的读取和写入,在python中还有其它方法,比如说pandas。鉴于最近粉丝朋友问到上面的“xlrd”和“xlwt”,那么笔者下面将通过这两个方法,来实现excel文件数据的读取和写入。首先,我们先需要提前安装好对应的库。需要注意的是,xlrd从2.0版本开始,只......
  • python_进程与线程_多线程
    一、程序与进程的概念1、进程:指启动后的程序,系统会为进程分配内存空间二、创建进程的方式1、第一种创建进程的方式process(group=None,target,name,args,kwargs)group:表示分组,实际上不使用,默认为None即可target:表示子进程要执行的任务,支持函数名name:表示子进程的......
  • python_网络编程_socket
    一、网络编程的基本概念通信协议:internet协议,任何私有网络支持此协议,就可以接入互联网二、七层协议与四层协议从下到上分别是:物理层、数据链路层、网络层、传输层、会话层、表示层、应用层三、掌握TCP、IP协议ip协议是整个TCP、IP协议族的核心IP地址就是会联网上计算......
  • 你能对 Python 类型注释进行模式匹配吗?
    你能在Python类型上进行模式匹配吗?我见过简单的例子:importbuiltinsmatchx:casebuiltins.str:print("matchedstr")casebuildins.int:print("matchedint")但我想在嵌套类型上进行模式匹配,比如Annotated[Optional[Literal["a",......
  • python Polars:替换嵌套列表的元素
    有谁知道是否可以有效地替换极坐标中嵌套列表的元素。例如:s=pl.Series('s',[[1,2,3],[3,4,5]])#replace3with10toget[[1,2,10],[10,4,5]]我已经尝试过s.to_frame().with_columns(pl.when(pl.col('s')==3)...)但是pl.when不喜欢List[bo......
  • Python 中的常量应该大写吗?
    在PEP8中,一般规则是在UPPER_CASE字符中声明常量。在现实生活中,可能有多种情况:#!envpythonDATABASE_HOST='localhost'app=Flask('myapp')base_two=partial(int,base=2)通常我们将字符串类型或数字类型变量视为不可变的,因此是常量,而不是对象或函数。问题是......
  • 多重处理会导致 Python 崩溃,并给出一个错误:调用 fork() 时可能已在另一个线程中进行
    我对Python比较陌生,并试图为我的for循环实现一个多处理模块。我在img_urls中存储了一个图像url数组,我需要下载并应用一些Google视觉。if__name__=='__main__':img_urls=[ALL_MY_Image_URLS]runAll(img_urls)print("---%sseconds---"%(......
  • Python编程时输入操作数错误
    我正在用Python编写下面的代码来模拟控制系统。但是,当我调试代码时,我面临以下问题:matmul:输入操作数1没有足够的维度(有0,gufunc核心,签名为(n?,k),(k,m?)->(n?,m?)需要1)文件“D:\ÁreadeTrabalho\GitHub\TCC\CódigosMarcela\SistemaSISO_tres_estados_new.py”,......
  • Python入门知识点 7--散列类型与字符编码
    1、初识散列类型(无序序列)数据类型分为3种:   前面已经学过了两种类型   1.数值类型:int/float/bool只能存储单个数据      2.序列类型:str/list/tuple,有序的存储多个数据--有序类型,有下标,可以进行索引切片步长操作          3.散列类型......
  • Python入门知识点 6--序列类型的方法
    1、初识序列类型方法序列类型的概念:数据的集合,在序列类型里面可以存放任意的数据也可以对数据进行更方便的操作这个操作就是叫增删改查(crud)(增加(Creat),读取查询(Retrieve),更新(Update),删除(Delete)几个单词的首字母简写)增删改查是操作数据最底层的操作(从本质......