具有数据类的SQLAlchemy默认不填充Postgres数据库 [英] SQLAlchemy with dataclass default not populating postgres database
问题描述
我正在使用 dataclasses
与SQLAlchemy经典映射范例相结合。当我定义 dataclass
并结合 int
和 str $ c的默认值时$ c>字段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 str
s, 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)
session.commit()
这正确地填充了 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数据库的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!