为了了解有关python的更多信息,我制作了以下简单脚本:
#!/usr/bin/env python
# coding=utf-8
# -*- Mode: python; c-basic-offset: 4 -*-
from sqlalchemy import *
from sqlalchemy.orm import sessionmaker
from sqlalchemy.orm import mapper
db=create_engine('postgresql://somepassword:someuser@127.0.0.1/hello')
db.echo = False
metadata = MetaData(db)
people=Table('people',metadata,autoload=True)
class People(object):
pass
people_mapper=mapper(People,people)
db_session=sessionmaker()
db_session.configure(bind=db)
lewis_hamilton=People()
lewis_hamilton.name='Lewis'
lewis_hamilton.surname='Hamilton'
lewis_hamilton.age=44
db_session.save(lewis_hamilton)
db_session.flush()
我使用下表" Lewis Hamilton"将被插入(直接来自psql):
Table "public.people"
Column | Type | Modifiers
---------+-----------------------+-----------------------------------------------------
id | integer | not null default nextval('people_id_seq'::regclass)
name | character varying(60) |
surname | character varying(60) |
age | smallint |
但是当我运行脚本时,我收到以下错误:
sqlalchemy.exc.ArgumentError:Mapper Mapper | People | people无法为映射表组装任何主键列' people'
我也看到了以下问题,但没有提供我想要的答案:
因为我使用自动加载来加载sql映射。
答案 0 :(得分:5)
关于数据库URI格式:用户名在用户密码之前,因此在您的示例中应该是'postgresql://someuser:somepassword@127.0.0.1/hello'
。
我们可以在create_engine
中传递echo
标记:它比设置属性更好,而且默认设置为False
,所以我们不需要特别是在特定情况下。
如果您不想用Table
个对象编写Column
对象架构(Describing Databases with MetaData更多信息) - 只需reflect your metadata
并获取来自'people'
对象的tables
field的metadata
表。
sessionmaker
是Session
个对象factory,而不是Session
个对象,因此您应该使用双重调用(看起来很难看)或提取sessionmaker
个实例作为单独的对象(在我们的例子中,我们将其称为session_factory
)。
AFAIK Session
个对象没有方法save
,但add
。
如果我们想要保存我们的更改(将lewis_hamilton
记录添加到表中),我们应该最后调用commit
方法,因为flush
与数据库通信但没有提交更改记录将丢失(在您的情况下,我们可以在没有flush
方法调用的情况下工作,您可以阅读有关flush
与commit
here}的更多信息。
所有这些评论都应该起作用
from sqlalchemy import *
from sqlalchemy.orm import sessionmaker
from sqlalchemy.orm import mapper
db = create_engine('postgresql://someuser:somepassword@127.0.0.1/hello')
metadata = MetaData(db)
# reflecting 'people' table from database schema
metadata.reflect(only=['people'])
people = metadata.tables['people']
class People(object):
pass
people_mapper = mapper(People, people)
session_factory = sessionmaker(bind=db)
db_session = session_factory()
lewis_hamilton = People()
lewis_hamilton.name = 'Lewis'
lewis_hamilton.surname = 'Hamilton'
lewis_hamilton.age = 44
db_session.add(lewis_hamilton)
db_session.commit()
但是使用people
对象创建Table
Column
对象而不是像
people = Table('people', metadata,
Column('id', Integer, primary_key=True),
Column('name', String(60)),
Column('surname', String(60)),
Column('age', SmallInteger))
此外,如果您想将People
类与Object Relational Tutorial后面的'people'
表格进行映射,我们会有类似的内容
from sqlalchemy import *
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
db = create_engine('postgresql://someuser:somepassword@127.0.0.1/hello')
metadata = MetaData(db)
people = Table('people', metadata,
Column('id', Integer, primary_key=True),
Column('name', String(60)),
Column('surname', String(60)),
Column('age', SmallInteger))
Base = declarative_base(metadata=metadata)
class People(Base):
__table__ = people
或没有people
Table
对象:
from sqlalchemy import *
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
db = create_engine('postgresql://someuser:somepassword@127.0.0.1/hello')
metadata = MetaData(db)
Base = declarative_base(metadata=metadata)
class People(Base):
__tablename__ = 'people'
id = Column('id', Integer, primary_key=True)
name = Column('name', String(60))
surname = Column('surname', String(60))
age = Column('age', SmallInteger)
我们也可以添加__init__
method,最后我们会有
from sqlalchemy import *
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
db = create_engine('postgresql://someuser:somepassword@127.0.0.1/hello')
metadata = MetaData(db)
Base = declarative_base(metadata=metadata)
class People(Base):
__tablename__ = 'people'
id = Column('id', Integer, primary_key=True)
name = Column('name', String(60))
surname = Column('surname', String(60))
age = Column('age', SmallInteger)
def __init__(self, name, surname, age):
self.name = name
self.surname = surname
self.age = age
session_factory = sessionmaker(bind=db)
db_session = session_factory()
lewis_hamilton = People(name='Lewis',
surname='Hamilton',
age=44)
db_session.add(lewis_hamilton)
db_session.commit()
正如PEP-8所说:
应该避免使用通配符导入(来自import *),因为它们不清楚命名空间中存在哪些名称,这会使读者和许多自动化工具混淆。通配符导入有一个可防御的用例,即将内部接口重新发布为公共API的一部分(例如,使用可选加速器模块中的定义覆盖接口的纯Python实现,以及确切的定义将是被覆盖的事先不知道。
所以你的行
from sqlalchemy import *
应该更加具体,因为里面有很多东西而且你并不需要它们。