【发布时间】:2018-09-29 08:37:27
【问题描述】:
我有一个Person 和id、fname 和lname 的课程。我的程序将包含大量 Person 对象,我想将其插入到我的 PostgreSQL 数据库中。
我想通过psycopg2.execute_values 方法来做到这一点,该方法需要为我的班级定义__getitem__。
__getitem__ 当前正在返回tuple(id, fname, lname),这导致pscopg2.execute_values 尝试执行:insert into persons(id, fname, lname) values ((1, 'test1', 'test1'))...
import psycopg2.extras
class Person:
def __init__(self, id, fname, lname):
self.id = id
self.fname = fname
self.lname = lname
def __len__(self):
return 1
def __getitem__(self, item):
return self.id, self.fname, self.lname
dsn = "user=my_user host=localhost port=5432 dbname=my_db"
query = "insert into persons(id, fname, lname) values %s"
p1 = Person(1, 'test1', 'test1')
p2 = Person(2, 'test2', 'test2')
records = list()
records.append(p1)
records.append(p2)
with psycopg2.connect(dsn=dsn) as conn:
with conn.cursor() as cursor:
psycopg2.extras.execute_values(cursor, query, records, template=None, page_size=1000)
psycopg2.ProgrammingError: INSERT has more target columns than expressions
LINE 1: insert into persons(id, fname, lname) values ((1, 'test1', 'test1'))...
^
HINT: The insertion source is a row expression containing the same number of columns expected by the INSERT. Did you accidentally use extra parentheses?
使用namedtuple 有效:
from collections import namedtuple
import psycopg2.extras
Person = namedtuple('Person', ['id', 'fname', 'lname'])
dsn = "user=my_user host=localhost port=5432 dbname=my_db"
query = "insert into persons(id, fname, lname) values %s"
p1 = Person(1, 'test1', 'test1')
p2 = Person(2, 'test2', 'test2')
records = list()
records.append(p1)
records.append(p2)
with psycopg2.connect(dsn=dsn) as conn:
with conn.cursor() as cursor:
psycopg2.extras.execute_values(cursor, query, records, template=None, page_size=1000)
但是,我想实现不同的 __eq__ 和 __hash__ 实现。如果有办法为namedtuple 覆盖这些方法,那么我愿意采用这种方法。
否则如何修改__getitem__分别返回id、fname和lname,使得查询变为:
insert into persons(id, fname, lname) values (1, 'test1', 'test1')...
【问题讨论】: