我正在尝试弄清楚如何在 SQLAlchemy 中对数据类使用声明性映射。
设置:
from dotenv import load_dotenv
import os
from sqlalchemy.engine import URL
#test abc
load_dotenv()
url_object = URL.create(
"postgresql+psycopg2",
username=os.environ.get('DBUSER'),
password=os.environ.get('DBPASS'), # plain (unescaped) text
host=os.environ.get('DBIP'),
database=os.environ.get('DBNAME'),
port=os.environ.get('DBPORT')
)
from sqlalchemy import create_engine, Table, Column, ForeignKey, Integer, String, Boolean
engine = create_engine(url_object,
echo=True)
from typing_extensions import Annotated
from typing import List
from typing import Optional
from sqlalchemy import ForeignKey
from sqlalchemy import String
from sqlalchemy.orm import DeclarativeBase
from sqlalchemy.orm import Mapped
from sqlalchemy.orm import MappedAsDataclass
from sqlalchemy.orm import mapped_column
from sqlalchemy.orm import relationship
from sqlalchemy.orm import registry
reg = registry()
class Base(MappedAsDataclass, DeclarativeBase):
"""subclasses will be converted to dataclasses"""
我可以像这样创建一个简单的映射类和关联表:
class Test(Base):
__tablename__ = 'test'
id: Mapped[int] = mapped_column(init=False, primary_key=True)
intVar: Mapped[int]
strVar: Mapped[str]
Test.__table__
Base.metadata.create_all(engine)
表按预期创建,包含“id”、“intVar”和“strVar”列
但是,当我尝试使用默认值创建变量时,不会创建这些列,我的表只有前四个。当我查看表 test2 时,我只看到前四列,没有看到最后三列。所有未创建列的变量都有默认值:
import datetime
class Test2(Base):
__tablename__ = 'test2'
id: Mapped[int] = mapped_column(init=False, primary_key=True)
intVar: Mapped[int]
strVar: Mapped[str]
anotherVar: Mapped[str]
optVar: Mapped[Optional[str]] = ''
yaVAR: Mapped[str] = ''
date: Mapped[datetime.datetime] = datetime.datetime.now()
Test2.__table__
Base.metadata.create_all(engine)
但是,据我所知,我需要可选变量的默认值,否则如果我尝试创建一个没有“可选”变量的类实例,它会抱怨缺少位置参数:
import datetime
class Test3(Base):
__tablename__ = 'test3'
id: Mapped[int] = mapped_column(init=False, primary_key=True)
intVar: Mapped[int]
strVar: Mapped[str]
anotherVar: Mapped[str]
optVar: Mapped[Optional[str]]
yaVAR: Mapped[str]
date: Mapped[datetime.datetime] = datetime.datetime.now()
Test3.__table__
Base.metadata.create_all(engine)
t3 = Test3(intVar = 0, strVar = 'abc', anotherVar = 'xyz', optVar = "bs", yaVAR='morebs', date = datetime.datetime.now())
t4 = Test3(intVar = 0, strVar = 'abc', anotherVar = 'xyz', yaVAR='morebs', date = datetime.datetime.now())
t4 = Test3(intVar = 0, strVar = 'abc', anotherVar = 'xyz', yaVAR='morebs', date = datetime.datetime.now())
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: __init__() missing 1 required positional argument: 'optVar'
好的,所以我误解了如何创建可选变量。当我使用
mapped_column(default=None)
而不是 Mapped[Optional[]]
时,一切都按预期工作。
class Error(Base):
__tablename__ = 'errors'
id: Mapped[int] = mapped_column(init=False, primary_key=True)
feed_id: Mapped[int]
url: Mapped[str]
error: Mapped[str]
step: Mapped[str]
host: Mapped[str]
parameters: Mapped[Optional[str]] = mapped_column(default=None)
uagent: Mapped[Optional[str]] = mapped_column(default=None)
proxy: Mapped[Optional[str]] = mapped_column(default=None)
status_code: Mapped[Optional[int]] = mapped_column(default=None)
date: Mapped[datetime.datetime] = mapped_column(default=None)