PostgreSQL有表学生:
Table "public.student"
Column | Type | Modifiers
--------+-----------------------+------------------------------------------------------
id | integer | not null default nextval('student_id_seq'::regclass)
name | character varying(10) |
sex | character varying(6) |
age | integer |
Indexes:
"student_pkey" PRIMARY KEY, btree (id)
我可以插入这样的记录:
Base = declarative_base()
class TableObject(Base):
__table__ = Table('student', metadata, autoload=True)
record = TableObject(name="tom", sex="male")
session.add(record)
record = TableObject(name="alice", sex="female", age=10)
session.add(record)
我希望有一种方法是这样的:
record = TableObject("alice", "female", 10)
session.add(record)
导致错误
TypeError: __init__() takes exactly 1 argument (4 given)
因为我会从文件中获取记录,并将每一行拆分为列表,所以如果支持这种方法,那将非常方便。
有什么办法吗?
答案 0 :(得分:2)
您可以立即插入记录,因为declarative_base
包含一个带有命名参数的构造函数。该construtor的代码如下(逐字github repository):
def _declarative_constructor(self, **kwargs):
"""A simple constructor that allows initialization from kwargs.
Sets attributes on the constructed instance using the names and
values in ``kwargs``.
Only keys that are present as
attributes of the instance's class are allowed. These could be,
for example, any mapped columns or relationships.
"""
cls_ = type(self)
for k in kwargs:
if not hasattr(cls_, k):
raise TypeError(
"%r is an invalid keyword argument for %s" %
(k, cls_.__name__))
setattr(self, k, kwargs[k])
_declarative_constructor.__name__ = '__init__'
因此,如果您想用位置版本替换此构造函数,那么它将适用于您的所有模型。以下可能是一个开始的地方:
def _declarative_positional_constructor(self, *args, **kwargs):
assert len(kwargs) == 0
column_names = tuple(c.name for c in self.__mapper__.columns if not(c in self.__mapper__.primary_key))
assert len(column_names) == len(args)
for name, value in zip(column_names, args):
setattr(self, name, value)
_declarative_positional_constructor.__name__ = '__init__'
# ...
# use own default constructor
Base = declarative_base(constructor = _declarative_positional_constructor)
但是,在这种情况下,使用名称创建实例的方法不起作用。所以你可以增强它来处理这两个版本
要检查的另一件事是保证autoload
保证表中列的顺序是相同的,以防止“男性”作为名称存储,而“John”被写入Gender列。 / p>
答案 1 :(得分:0)
你能使用这样的方法:
class TableObject(Base):
def __init__(self, name, sex, age):
super(TableObject, self).__init__()
self.name = name
self.sex = sex
self.age = age