基础入门_Python-模块和包.深入SQLAlchemy之SQLAlchemy ORM重构表?

简单介绍:

说明: 此模块主要用于将关系型数据库表映射到PY的类,行映射到PY类的实例,列映射为PY实例的属性,由于其兼容众多DB-API及扩展,SO可以优先考虑数据模型,而忽略底层的DB-API切换,数据迁移更方便.

快速安装:


pip install --upgrade SQLAlchemy


定义结构:


#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
#
# Authors: limanman
# OsChina: http://xmdevops.blog.51cto.com/
# Purpose:
#
"""
# 说明: 导入公共模块
from datetime import datetime
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import (create_engine, MetaData, Table, Column, Integer, String, DateTime, Numeric,
                        ForeignKey, PrimaryKeyConstraint, ForeignKeyConstraint, UniqueConstraint)
# 说明: 导入其它模块
from constants import USERNAME, PASSWORD, HOSTNAME, HOSTPORT, DATABASE, CHARSSET, ALLDBURI
Base = declarative_base()
class Cookies(Base):
    __tablename__ = ‘cookies‘
    id = Column(Integer(), primary_key=True, autoincrement=True)
    cookie_name = Column(String(50), index=True)
    cookie_recipe_url = Column(String(255))
    cookie_sku = Column(String(55))
    quantity = Column(Integer())
    unit_cost = Column(Numeric(12, 2))


说明: SQLAlchemy ORM与SQLAlchemy Core有些许不同,用户只用关注上层数据对象定义,之前我们还需要定义metadata容器对象让表对象引用它,而在ORM中只需要定义的表类继承自declarative_base实例基类则会自动关联表对象和metadata对象,而无需关注底层的实现.

注意: 要定义一个ORM的表类,需要满足至少四个条件,必须继承自declarative_base实例,必须包含一个__tablename__类属性,值为对应数据库中的表名,必须至少包含一个或是更多的列属性,必须至少有一个或更多列作为主键

索引约束:


class Cookies(Base):
    __tablename__ = ‘cookies‘
    __table_args__ = (PrimaryKeyConstraint(‘id‘))
    id = Column(Integer(), autoincrement=True)
    cookie_name = Column(String(50), index=True)
    cookie_recipe_url = Column(String(255))
    cookie_sku = Column(String(55))
    quantity = Column(Integer())
    unit_cost = Column(Numeric(12, 2))


说明: SQLAlchemy Core中可直接在定义Table时定义表级约束/索引,在SQLAlchemy ORM中也可以很方便实现,可通过设置表类的__table_args__ 类属性来设置多个索引和约束,值可为序列对象,PrimaryKeyConstraint, ForeignKeyConstraint, UniqueConstraint的用法和SQLAlchemy Core是一样的~

关系映射:

说明: 如上图,一个用户可以产生多个订单,所以在orders表中创建外键user_id关联users表,而每个订单又可以包含多个商品,且可以包含多个相同的商品最终还得有一个最终价格,所以在line_items中创建外键order_id关联orders,又因为每个商品有具体详情所以在line_items中创建外键cookie_id关联cookies


#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
#
# Authors: limanman
# OsChina: http://xmdevops.blog.51cto.com/
# Purpose:
#
"""
# 说明: 导入公共模块
from datetime import datetime
from sqlalchemy.orm import relationship, backref
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import (create_engine, Column, Integer, String, DateTime, Numeric, ForeignKey)
# 说明: 导入其它模块
from constants import USERNAME, PASSWORD, HOSTNAME, HOSTPORT, DATABASE, CHARSSET, ALLDBURI
Base = declarative_base()
class Users(Base):
    __tablename__ = ‘users‘
    id = Column(Integer(), primary_key=True, autoincrement=True)
    customer_number = Column(Integer(), autoincrement=True)
    username = Column(String(15), unique=True, nullable=False)
    email_address = Column(String(255), nullable=False)
    phone = Column(String(20), nullable=False)
    password = Column(String(25), nullable=False)
    created_on = Column(DateTime(), default=datetime.now)
    updated_on = Column(DateTime(), default=datetime.now, onupdate=datetime.now)
class Orders(Base):
    __tablename__ = ‘orders‘
    id = Column(Integer(), primary_key=True, autoincrement=True)
    user_id = Column(Integer(), ForeignKey(‘Users.id‘), nullable=False)
    user = relationship(‘Users‘, backref=backref(‘orders‘, order_by=id))
class LineItems(Base):
    __tablename__ = ‘line_items‘
    id = Column(Integer(), primary_key=True, autoincrement=True)
    quantity = Column(Integer())
    extended_cost = Column(Numeric(12, 2))
    order_id = Column(Integer(), ForeignKey(‘Orders.id‘), nullable=False)
    cookie_id = Column(Integer(), ForeignKey(‘Cookies.id‘), nullable=False)
    order = relationship(‘Orders‘, backref=backref(‘line_items‘, order_by=id))
    cookies = relationship(‘Cookies‘, backref=backref(‘line_item‘, uselist=False))
class Cookies(Base):
    __tablename__ = ‘cookies‘
    id = Column(Integer(), primary_key=True, autoincrement=True)
    cookie_name = Column(String(50), index=True)
    cookie_recipe_url = Column(String(255))
    cookie_sku = Column(String(55))
    quantity = Column(Integer())
    unit_cost = Column(Numeric(12, 2))
if __name__ == ‘__main__‘:
    # 第一步: 创建引擎对象
    engine = create_engine(ALLDBURI, echo=True, pool_recycle=3600)
    # 第二步: 创建元数据对象
    Base.metadata.create_all(bind=engine)


说明: 如上简单演示了SQLAlchemy ORM常见建表过程,和SQLAlchemy Core不同,它强制通过relationship和backref来为关联表类增加互相指向的类属性,relationship的第一个参数为要关联的表类名称,常用的还有backref,通过backref创建,第一个参数为支持另一个表反向访问的属性名,剩余的relationship和backref的参数一样的,如上的uselist=False表示反向引用时是one2one模式,更多参数可以参考源码实例Lib/site-packages/sqlalchemy/orm/relationships.py

时间: 2024-08-07 04:14:09

基础入门_Python-模块和包.深入SQLAlchemy之SQLAlchemy ORM重构表?的相关文章

基础入门_Python-模块和包.深入SQLAlchemy之列级别约束与表级别约束?

简单介绍: 说明: 此模块主要用于将关系型数据库表映射到PY的类,行映射到PY类的实例,列映射为PY实例的属性,由于其兼容众多DB-API及扩展,SO可以优先考虑数据模型,而忽略底层的DB-API切换,数据迁移更方便. 快速安装: pip install --upgrade SQLAlchemy 创建引擎: 1. 连接数据库前需创建引擎,作为执行SQL的接口,其实底层通过Pool(连接池)和Dialect(翻译器)将映射后的PY语句转换为对应DB-API支持的原生SQL语句去执行,这样写PY时就

基础入门_Python-模块和包.深入Celery之常用架构/方案选型/必知必会?

简单介绍: 说明: 此模块是一个专注于分布式消息传递的异步任务队列,所谓任务就是消息,消息中的有效载荷中包含要执行的任务需要的全部数据 几大特性: 1. Celery易于使用和维护,且不需要配置文件,默认配置启动时自动写入消息代理. 2. Celery高可用,连接丢失或失败时客户端或消费者会自动重试,并且可通过消息代理的双主/主从模式来提高高可用性 3. Celery快速,单个进程每分钟可处理百万任务,且优化后可保持往返延迟在亚毫秒级别 4. Celery灵活,几乎所有部分都支持扩展或单独使用,

2015/9/15 Python基础(12):模块和包

模块是用来组织 Python 代码的方法,而包则是用来组织模块的. 当代码量很大时,我们一般会把代码分成几个有组织的代码段,然后每个代码段之间有一定的联系.代码单之间是共享的,所以Python允许调入一个模块,允许使用其他模块的属性利用之前的工作成果,实现代码重用.那些自我包含并且有组织的代码片段就是模块(module),将其他模块中属性附加到你的模块中的操作较导入(import) 模块是逻辑上的说法,而它们在物理层是一个个独立的文件,模块的文件名就是模块的名字加拓展名.py.与其他可以导入类的

基础入门_Python-模块和包.运维开发中日志模块logging的最佳实践?

简单介绍: 说明: 此模块儿提供了文件,HTTP GET/POST,SMTP,SOCKET等方式实现日志记录,甚至可以自动实现具体的日志记录方式 快速安装: pip install --upgrade logging 处理流程: 日志级别: 属性名称 属性说明 logging.NOTSET 默认为0 logging.DEBUG 调试为10 logging.INFO 一般为20 logging.WARN 警告为30 logging.ERROR 错误为40 logging.CRITICAL 严重为5

基础入门_Python-模块和包.深入Celery之应用配置/独立模块配置实践?

配置简介: 说明: Celery的配置文件非常强大,支持在应用上设置,也可以使用一个独立的配置模块,具体需要调整的默认选项可通过http://docs.jinkan.org/docs/celery/configuration.html#configuration 获取. # 方式一 : 直接在应用上设置,通过app.conf.update可一次性设置多个选项,常用于小型项目 #!/usr/bin/env python # -*- coding: utf-8 -*- # @Date    : 20

基础入门_Python-模块和包.深入SQLAlchemy之玩转各种增删查改操作?

增加数据: # 单行数据(from sqlalchemy import ...) conn = engine.connect() # 方式一: 调用表对象的insert ins = cookies.insert().values(     cookie_name='chocolate chip',     cookie_recipe_url='http://some.aweso.me/cookie/recipe.html',     cookie_sku='CC01',     quantity

基础入门_Python-模块和包.深入SQLAlchemy之事务回滚与反射还原对象?

异常处理: # 异常一: AttributeError,对象属性不存在 with engine.connect() as conn:     trans = conn.begin()     s = select([users])     try:         r = conn.execute(s)         for record in r:             print record.Password     except AttributeError, e:         

基础入门_Python-模块和包.运维开发中inspect自省模块的最佳实践?

简单介绍: 说明: 此模块提供了一系列自省函数,可获取模块/类/方法/函数/traceback/帧对象/代码对象的信息 快速安装: 内置模块 测试相关: inspect.ismodule(object) -> True/False 说明: 判断object是否为模块 inspect.isclass(object) -> True/False 说明: 判断object是否为类 inspect.ismethod(object) -> True/False 说明: 判断object是否为方法

基础入门_Python-模块和包.运维开发中内建模块getopt的最佳实践?

简单介绍: 此模块提供命令行选项解析,目前支持短格式和长格式选项 快速安装: 说明:  内建模块无需安装 解析方法: getopt(args, shortopts, longopts = []) -> (opts, args) 说明: args为要解析的参数序列,常为sys.argv[1:],shortopts为单字符选项定义串,如果某个选项需要一个参数,响应字母后面必须有一个冒号,longopts为长格式的选项名序列,可以包含多个字符,序列元素必须包含--前缀,如果此长选项需要参数则其名应包含