sqlachemy详解
实习期老大让我学Python...学了很久了好吗,不过确实对其中的一些原理性的东西还不够深入.
比如今天要说的sqlachemy,结合网上做些总结吧
ORM 全称 Object Relational Mapping, 翻译过来叫对象关系映射。简单的说,ORM 将数据库中的表与面向对象语言中的类建立了一种对应关系。这样,我们要操作数据库,数据库中的表或者表中的一条记录就可以直接通过操作类或者类实例来完成。
1.安装
sudo pip install sqlalchemy
2.建数据库和数据表
# coding: utf-8
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, String, Integer
from sqlalchemy.orm import sessionmaker
# 链接数据库采用mysqldb模块做映射
engine = create_engine('mysql+mysqldb://root:mysql@localhost:3306/blog?charset=utf8')
# 创建对象的基类:
Base = declarative_base()
# 定义User对象:
class User(Base):
# 表名
__tablename__ = 'users'
# 表结构
# Column代表数据库中的一列,nullable=False代表这一列不可以为空,index=True表示在该列创建索引
id = Column(Integer, primary_key=True)
username = Column(String(64), nullable=False, index=True)
password = Column(String(64), nullable=False)
email = Column(String(64), nullable=False, index=True)
# __repr__ 方便调试,可以不定义
def __repr__(self):
return '%s(%r)' % (self.__class__.__name__, self.username)
# 执行建表命令
if __name__ == '__main__':
Base.metadata.create_all(engine)
3.关系演示
3.1 一对多关系
对于一个普通的博客应用来说,用户和文章显然是一个一对多的关系,一篇文章属于一个用户,一个用户可以写很多篇文章,那么他们之间的关系可以这样定义:
class User(Base):
__tablename__ = 'users'
id = Column(Integer, primary_key=True)
username = Column(String(64), nullable=False, index=True)
password = Column(String(64), nullable=False)
email = Column(String(64), nullable=False, index=True)
articles = relationship('Article')
def __repr__(self):
return '%s(%r)' % (self.__class__.__name__, self.username)
class Article(Base):
__tablename__ = 'articles'
id = Column(Integer, primary_key=True)
title = Column(String(255), nullable=False, index=True)
content = Column(Text)
user_id = Column(Integer, ForeignKey('users.id'))
author = relationship('User')
def __repr__(self):
return '%s(%r)' % (self.__class__.__name__, self.title)
每篇文章有一个外键指向 users 表中的主键 id, 而在 User 中使用 SQLAlchemy 提供的 relationship 描述 关系。而用户与文章的之间的这个关系是双向的,所以我们看到上面的两张表中都定义了 relationship。
SQLAlchemy 提供了 backref 让我们可以只需要定义一个关系:
articles = relationship('Article', backref='author')
添加了这个就可以不用再在 Article 中定义 relationship 了!
3.2 一对一关系
在 User 中我们只定义了几个必须的字段, 但通常用户还有很多其他信息,但这些信息可能不是必须填写的,我们可以把它们放到另一张 UserInfo 表中,这样User 和 UserInfo 就形成了一对一的关系。你可能会奇怪一对一关系为什么不在一对多关系前面?那是因为一对一关系是基于一对多定义的:
class User(Base):
__tablename__ = 'users'
id = Column(Integer, primary_key=True)
username = Column(String(64), nullable=False, index=True)
password = Column(String(64), nullable=False)
email = Column(String(64), nullable=False, index=True)
articles = relationship('Article', backref='author')
userinfo = relationship('UserInfo', backref='user', uselist=False)
def __repr__(self):
return '%s(%r)' % (self.__class__.__name__, self.username)
class UserInfo(Base):
__tablename__ = 'userinfos'
id = Column(Integer, primary_key=True)
name = Column(String(64))
qq = Column(String(11))
phone = Column(String(11))
link = Column(String(64))
user_id = Column(Integer, ForeignKey('users.id'))
定义方法和一对多相同,只是需要添加 userlist=False 。
3.3 多对多关系
一遍博客通常有一个分类,好几个标签。标签与博客之间就是一个多对多的关系。多对多关系不能直接定义,需要分解成俩个一对多的关系,为此,需要一张额外的表来协助完成:
article_tag = Table(
'article_tag', Base.metadata,
Column('article_id', Integer, ForeignKey('articles.id')),
Column('tag_id', Integer, ForeignKey('tags.id'))
)
class Tag(Base):
__tablename__ = 'tags'
id = Column(Integer, primary_key=True)
name = Column(String(64), nullable=False, index=True)
def __repr__(self):
return '%s(%r)' % (self.__class__.__name__, self.name)
4.增删改查
要完成数据库查询,就需要建立与数据库的连接。这就需要用到Engine对象。一个Engine可能是关联一个Session对象,也可能关联一个数据库表。
当然Session最重要的功能还是实现原子操作。
你可以把 sessionmaker 想象成一个手机,engine 当做 MySQL 的号码,拨通这个“号码”我们就创建了一个 Session 类,下面就可以通过这个类的实例与 MySQL 愉快的交谈了
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
some_engine = create_engine('nysql://username:password@localhost/mydb?charset=utf8')
# 创建Session类型:
Session = sessionmaker(bind=some_engine)
# 创建session对象:
session = Session()
4.1增
# 创建新User对象:
new_user = User(id='5', name='Bob')
# 添加到session:
session.add(new_user)
# 提交即保存到数据库:
session.commit()
# 关闭session:
session.close()
4.2查
# 创建Query查询,filter是where条件,最后调用one()返回唯一行,如果调用all()则返回所有行:
user = session.query(User).filter(User.id=='5').one()
# 打印类型和对象的name属性:
print('type:', type(user))
print('name:', user.name)
# 关闭Session:
session.close()
4.3更新
user = session.query(User).filter_by(name="user1").first()
user.password = "newpassword"
session.commit()
session.close()
4.4删
user = session.query(User).filter_by(name="user1").first()
session.delete(user)
session.commit()
session.close()
排版什么的以后再改,学无止境
sqlachemy详解的更多相关文章
- Linq之旅:Linq入门详解(Linq to Objects)
示例代码下载:Linq之旅:Linq入门详解(Linq to Objects) 本博文详细介绍 .NET 3.5 中引入的重要功能:Language Integrated Query(LINQ,语言集 ...
- 架构设计:远程调用服务架构设计及zookeeper技术详解(下篇)
一.下篇开头的废话 终于开写下篇了,这也是我写远程调用框架的第三篇文章,前两篇都被博客园作为[编辑推荐]的文章,很兴奋哦,嘿嘿~~~~,本人是个很臭美的人,一定得要截图为证: 今天是2014年的第一天 ...
- EntityFramework Core 1.1 Add、Attach、Update、Remove方法如何高效使用详解
前言 我比较喜欢安静,大概和我喜欢研究和琢磨技术原因相关吧,刚好到了元旦节,这几天可以好好学习下EF Core,同时在项目当中用到EF Core,借此机会给予比较深入的理解,这里我们只讲解和EF 6. ...
- Java 字符串格式化详解
Java 字符串格式化详解 版权声明:本文为博主原创文章,未经博主允许不得转载. 微博:厉圣杰 文中如有纰漏,欢迎大家留言指出. 在 Java 的 String 类中,可以使用 format() 方法 ...
- Android Notification 详解(一)——基本操作
Android Notification 详解(一)--基本操作 版权声明:本文为博主原创文章,未经博主允许不得转载. 微博:厉圣杰 源码:AndroidDemo/Notification 文中如有纰 ...
- Android Notification 详解——基本操作
Android Notification 详解 版权声明:本文为博主原创文章,未经博主允许不得转载. 前几天项目中有用到 Android 通知相关的内容,索性把 Android Notificatio ...
- Git初探--笔记整理和Git命令详解
几个重要的概念 首先先明确几个概念: WorkPlace : 工作区 Index: 暂存区 Repository: 本地仓库/版本库 Remote: 远程仓库 当在Remote(如Github)上面c ...
- Drawable实战解析:Android XML shape 标签使用详解(apk瘦身,减少内存好帮手)
Android XML shape 标签使用详解 一个android开发者肯定懂得使用 xml 定义一个 Drawable,比如定义一个 rect 或者 circle 作为一个 View 的背景. ...
- Node.js npm 详解
一.npm简介 安装npm请阅读我之前的文章Hello Node中npm安装那一部分,不过只介绍了linux平台,如果是其它平台,有前辈写了更加详细的介绍. npm的全称:Node Package M ...
随机推荐
- Oracle JDBC 连接卡死后 Connection Reset
坑 这绝对是我碰计算机以来遇到的第一大坑! 症状: 在Linux主机上远程登录,执行一个简单的Oracle的JDBC连接程序(jar包),结果硬生生的卡在了连接建立验证阶段,然后等上几分钟后因为连接超 ...
- Topcoder SRM 563 Div1 500 SpellCards
题意 [题目链接]这怎么发链接啊..... 有\(n\)张符卡排成一个队列,每张符卡有两个属性,等级\(li\)和伤害\(di\). 你可以做任意次操作,每次操作为以下二者之一: 把队首的符卡移动到队 ...
- 区域可编辑contenteditable的问题总结
一.如何在可编辑区域div的光标处通过点击事件来添加文本内容 下面的例子是可编辑div的区域添加文本内容和判断光标位置的方法 <!DOCTYPE html> <html lang=& ...
- Python 列表(list)操作
创建列表 sample_list = ['a',1,('a','b')] Python 列表操作 sample_list = ['a','b',0,1,3] 得到列表中的某一个值 value_star ...
- gluon实现softmax分类FashionMNIST
from mxnet import gluon,init from mxnet.gluon import loss as gloss,nn from mxnet.gluon import data a ...
- CFS调度分析(内核版本:2.6.34)
CFS调度分析(内核版本:2.6.34) 1.时间记账 CFS不再有时间片的概念,他维护的是每个进程运行的时间记账 使用调度器实体结构来追踪进程运行记账: <linux/sched.h> ...
- LA 4731 蜂窝网络
题目链接:https://vjudge.net/problem/UVALive-4731 题意: n 个 数,分成 w 组,求整个区间的数学期望的最小值: 一个区间的数学期望公式给出:一个区间的和 * ...
- c++字符串初始化
#include<string> string s1 = "abcdefg"; string s2("abcdefg");
- 解决 Your project contains error(s),please fix them before running your applica ..
解决 Your project contains error(s),please fix them before running your application问题 http://www.cnblo ...
- Android学习笔记_19_广播接收者 BroadcastReceiver及其应用_窃听短信_拦截外拨电话
一.广播接收者类型: 广播被分为两种不同的类型:“普通广播(Normal broadcasts)”和“有序广播(Ordered broadcasts)”. 普通广播是完全异步的,可以在同一时刻(逻辑上 ...