SQLAlchemy适当的模型定义和选择/插入

时间:2014-09-22 05:47:21

标签: python mysql sql database sqlalchemy

我在设置模型和选择/插入

时遇到了SQL Alchemy的问题

如果我按如下方式设置模型并将项目插入表中,则可以正常工作:

#!/usr/bin/python

import pymysql
import sqlalchemy
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import *
from sqlalchemy.orm import sessionmaker
from sqlalchemy.sql import select

engine = sqlalchemy.create_engine('mysql+pymysql://root@127.0.0.1/music?charset=utf8&use_unicode=0', pool_recycle=3600)
connection = engine.connect()

Base = declarative_base(bind=engine)
Base

metadata = MetaData()

directory = Table('directory', metadata,
    Column('id', Integer, primary_key=True),
    Column('size', Integer),
    Column('name', String, unique=True),
    )

words = Table('words', metadata,
    Column('id', Integer, primary_key=True),
    Column('source', Integer, ForeignKey('directory.id')),
    Column('words', String),
    )

ratios = Table('ratios', metadata,
    Column('id', Integer, primary_key=True),
    Column('source', Integer, ForeignKey('directory.id')),
    Column('target', Integer, ForeignKey('directory.id')),
    Column('ratio', Integer),
    )

metadata.create_all(engine)

# ---------------------------------------------------------------------
# Execute Insert
# ---------------------------------------------------------------------

i = words.insert().values(words='jack', source=1)
result = connection.execute(i)

但是,如果我使用上面的模型并尝试选择使用记录的ID(下面的命令),我得不到任何结果:

s = directory.select().where(id == 1)
result = connection.execute(s)

for r in result:
    print r

该表确实有一个带有该ID的记录,因此它应该返回一个结果!

如果我按如下方式设置模型/表并使用Select命令(如下所示),则可以:

#!/usr/bin/python

import pymysql
import sqlalchemy
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import *
from sqlalchemy import UniqueConstraint

engine = sqlalchemy.create_engine('mysql+pymysql://root@127.0.0.1/music?charset=utf8&use_unicode=0', pool_recycle=3600)
connection = engine.connect()


Base = declarative_base(bind=engine)
Base

class Directory(Base):
    __tablename__ = "directory"
    id = Column(Integer, primary_key=True)
    name = Column(String(767), unique=True)
    size = Column(Integer)

class Words(Base):
    __tablename__ = "words"
    id = Column(Integer, primary_key=True)
    source = Column(Integer, ForeignKey('directory.id'))
    words = Column(String(1500))

class Ratios(Base):
    __tablename__ = "ratios"
    id = Column(Integer, primary_key=True)
    source = Column(Integer, ForeignKey('directory.id'))
    target = Column(Integer, ForeignKey('directory.id'))
    ratio = Column(Integer)


class Rename(Base):
    __tablename__ = "rename"
    id = Column(Integer, primary_key=True)
    source = Column(Integer, ForeignKey('directory.id'))
    name = Column(String(1500))


Base.metadata.create_all()

# ---------------------------------------------------------------------
# Execute Select
# ---------------------------------------------------------------------

s = select([Directory]).where(Directory.id == 1)
result = connection.execute(s)

for r in result:
    print r

但是如果我遵循与Select for Insert类似的语法,那么这不起作用:

i = insert([Words]).values(source=1, words=out)
connection.execute(i)

问题: 有人可以推荐哪种风格的模型是正确的/最好的吗?

有人可以澄清插入,更新,选择推荐模型的语法吗?

是否有可以推荐的教程简洁明了?我一直在阅读SQLAlchemy文档并且它真的让人感到困惑 - 我找到了以上两种方式设置模型的示例,但是没有找到任何教程#34&#34 ;端至端"以一种直截了当的方式。

谢谢。

2 个答案:

答案 0 :(得分:2)

您是否故意不使用ORM?如果没有,请查看comprehensive ORM tutorial

以下是使用ORM选择,插入和更新示例的对象的工作示例:

import sqlalchemy
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import *
from sqlalchemy import orm

engine = sqlalchemy.create_engine('sqlite://')
connection = engine.connect()


Base = declarative_base()


class Directory(Base):
    __tablename__ = "directory"
    id = Column(Integer, primary_key=True)
    name = Column(String(767), unique=True)
    size = Column(Integer)

    def __repr__(self):
        return (
            "Directory(id={self.id}, name={self.name}, size={self.size}"
            .format(self=self))


class Words(Base):
    __tablename__ = "words"
    id = Column(Integer, primary_key=True)
    source = Column(Integer, ForeignKey('directory.id'))
    directory = orm.relationship('Directory', backref='words')
    words = Column(String(1500))

    def __repr__(self):
        return (
            "Words(id={self.id}, source={self.source}, words={self.words}"
            .format(self=self))


class Ratios(Base):
    __tablename__ = "ratios"
    id = Column(Integer, primary_key=True)
    source = Column(Integer, ForeignKey('directory.id'))
    target = Column(Integer, ForeignKey('directory.id'))
    ratio = Column(Integer)


class Rename(Base):
    __tablename__ = "rename"
    id = Column(Integer, primary_key=True)
    source = Column(Integer, ForeignKey('directory.id'))
    name = Column(String(1500))


def select_objs(session):
    #
    # Select examples
    #
    print 'Retrieving objects -----------------'
    word = session.query(Words).filter(Words.id == 1).first()
    print word
    print 'Access the directory via a relationship!'
    print word.directory
    print '---------------------------'


if __name__ == '__main__':
    engine = create_engine('sqlite://', echo=True)
    Session = orm.sessionmaker()
    Session.configure(bind=engine)
    Base.metadata.bind = engine
    Base.metadata.create_all()

    session = Session()

    #
    # Insert some objects
    #

    dir1 = Directory(id=1, name='Some Dir', size=10)
    session.add(dir1)
    # Note because of the relationship configuration and the fact that dir1
    # is already in the session, word doesn't have to be added
    # (no harm in doing so though)
    word = Words(id=1, directory=dir1, words='Some words!')
    session.flush()

    select_objs(session)

    #
    # Update them
    #

    # Update via ORM
    word.words = 'Some new words!'
    # update via query
    (
        session.query(Directory)
        .filter(Directory.id == 1)
        .update({"name": "A new directory name!"}))

    # Prove they're updated: flush session, expunge existing objects
    session.flush()
    session.expunge(word)

    select_objs(session)

答案 1 :(得分:0)

我得到了以下工作,但我不确定这是否是最好的方法:

#!/usr/bin/python

import pymysql
import sqlalchemy
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import *
from sqlalchemy.sql import select

engine = sqlalchemy.create_engine('mysql+pymysql://root@127.0.0.1/music?charset=utf8&use_unicode=0', pool_recycle=3600)
connection = engine.connect()

Base = declarative_base(bind=engine)
Base

metadata = MetaData()


directory = Table('directory', metadata,
    Column('id', Integer, primary_key=True),
    Column('size', Integer),
    Column('name', String, unique=True),
    )

words = Table('words', metadata,
    Column('id', Integer, primary_key=True),
    Column('source', Integer, ForeignKey('directory.id')),
    Column('wordlist', String),
    )

ratios = Table('ratios', metadata,
    Column('id', Integer, primary_key=True),
    Column('source', Integer, ForeignKey('directory.id')),
    Column('target', Integer, ForeignKey('directory.id')),
    Column('ratio', Integer),
    )

metadata.create_all(engine)


# ---------------------------------------------------------------------
# WORKING EXAMPLES
# ---------------------------------------------------------------------

# SELECT
# s = select([Directory]).where(Directory.name.like("%\smeta%"))

s = directory.select(directory.c.id==1)
rs = connection.execute(s)

for r in rs:
    print r

# INSERT
i = words.insert().values(source=1, wordlist='blah')
rsi = connection.execute(i)