我正在使用 dataclasses 与SQLAlchemy经典映射范例相结合。当我定义 dataclass 并结合 int 和 str 字段SQLAlchemy不会填充 int 和 str s,但是会填充列出和日期时间字段。例如以下代码:
I am using dataclasses combined with the SQLAlchemy classical mapping paradigm. When I define a dataclass combined with default values for the int and str fields SQLAlchemy does not populate the int and strs, but it does populate the List and datetime fields. For example the following code:
from dataclasses import dataclass, field from typing import List from datetime import datetime from sqlalchemy import create_engine, MetaData, Table, Column, Integer, String, ARRAY, TIMESTAMP from sqlalchemy.orm import sessionmaker, mapper metadata = MetaData() person_table = \ Table('people', metadata, Column('id', Integer, primary_key=True, autoincrement=True), Column('name', String(255)), Column('age', Integer), Column('hobbies', ARRAY(String)), Column('birthday', TIMESTAMP) ) @dataclass class Person: id: int = None name: str = '' age: int = 0 hobbies: List[str] = field(default_factory=list) birthday: datetime = field(default_factory=datetime) mapper(Person, person_table) engine = create_engine('postgresql://postgres@localhost:32771/test', echo=True) metadata.create_all(engine) session = sessionmaker(bind=engine)() person = Person(id=None, name='Robby', age=33, hobbies=['golf', 'hiking'], birthday=datetime(1985, 7, 25)) session.add(person) sessionmit()这正确地填充了 person 对象在内存中,但是 commit 操作在postgres中生成以下数据( name 和 age 列为 null ):
This correctly populates the person object in memory, but the commit operation produces the following data in postgres (the name and age columns are null):
id | name | age | hobbies | birthday ----+------+-----+---------------+--------------------- 1 | | | {golf,hiking} | 1985-07-25 00:00:00如果我更改 Person 类,从 name 和 age 中删除默认值,然后将数据正确填充到postgres:
If I change the Person class to remove the default values from name and age then the data is populated correctly in postgres:
@dataclass class Person: id: int = None name: str age: int hobbies: List[str] = field(default_factory=list) birthday: datetime = field(default_factory=datetime)请注意,我已验证在中创建 person 对象时在内存中正确填充 name 和 age 字段的类的版本。
Note, I have verified that when the person object is created in the "no-default" version of the class that the name and age fields are populated correctly in memory.
如何将SQLAlchemy经典映射与具有默认值的数据类一起使用?
How do I use SQLAlchemy classical mappings in conjunction with dataclasses with default values?
(Python 3.6,SQLAlchemy 1.2.16,PostgreSQL 11.2)
(Python 3.6, SQLAlchemy 1.2.16, PostgreSQL 11.2)
推荐答案由于''和 0 分别是默认返回值 str()和 int()函数,可以使用以下代码插入这些默认值:
Since '' and 0 are respectively default returned values of str() and int() functions, you could use the following code to insert thoses defaults:
@dataclass class Person: id: int = None name: str = field(default_factory=str) age: int = field(default_factory=int) hobbies: List[str] = field(default_factory=list) birthday: datetime = field(default_factory=datetime)不幸的是,由于某些原因,使用 default 参数函数中的 field()函数无法正常工作(可能是 dataclasses 向后移植的错误或误解...)。但是您仍然可以使用 default_factory 指定不同于''和 0 使用 lambda :
Unfortunately, for some reason, using default parameter of field() function does not work as we could expect (could be a bug of the dataclasses backport or a misunterstanding...). But you still can use the default_factory to specify values differents from '' and 0 using lambda:
@dataclass class Person: id: int = None name: str = field(default_factory=lambda: 'john doe') age: int = field(default_factory=lambda: 77) hobbies: List[str] = field(default_factory=list) birthday: datetime = field(default_factory=datetime)更多推荐
具有数据类的SQLAlchemy默认不填充Postgres数据库
发布评论