当前位置: 首页 > news >正文

SQLAlchemy 学习笔记

通信类型:AF_INET
协议家族一般是表示TCP通信的SOC_STREAM和UDP通信的SOCK_DGRAM。对于TCP通信,建立socket连接,:

    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

连接socket,

    s.connect((host,port))

socket通信建立连接后,利用它发送接收数据,python提供了两种方式:socket对象和文件类对象

socket对象提供了操作系统的send()、sendto()、recv()、recvfrom()方法,文件对象提供了read()、write()、readline()方法。

SQLAlchemy 学习笔记

SQLAlchemy是Python界的ORM(Object Relational Mapper)框架,它两个主要的组件: SQLAlchemy ORMSQLAlchemy Core

架构图

####安装

pip install SQLAlchemy
#检查安装是否成功:  
>>> import sqlalchemy
>>> sqlalchemy.__version__
0.8.0

没有报错就代表正确安装了,连接MySQL数据库(需要MySQLdb支持):

from sqlalchemy import create_engine
DB_CONNECT_STRING = 'mysql+mysqldb://root:@localhost/test2?charset=utf8'
engine = create_engine(DB_CONNECT_STRING,echo=True)

create_engine方法返回一个Engine实例,Engine实例只有直到触发数据库事件时才真正去连接数据库,如执行:

engine.execute("select 1").scalar()

执行上面的语句是,sqlalchemy就会从数据库连接池中获取一个连接用于执行语句。echo=True是回显命令,sqlalchemy与数据库通信的命令都将打印出来,例如:

2014-12-28 01:00:29,078 INFO sqlalchemy.engine.base.Engine SHOW VARIABLES LIKE ‘sql_mode’
2014-12-28 01:00:29,079 INFO sqlalchemy.engine.base.Engine ()
2014-12-28 01:00:29,080 INFO sqlalchemy.engine.base.Engine SELECT DATABASE()
2014-12-28 01:00:29,081 INFO sqlalchemy.engine.base.Engine ()
2014-12-28 01:00:29,083 INFO sqlalchemy.engine.base.Engine show collation where `Charset` = ‘utf8’ and `Collation` = ‘utf8_bin’
2014-12-28 01:00:29,083 INFO sqlalchemy.engine.base.Engine ()

####声明一个映射(declare a Mapping)

declarative_base类维持了一个从类到表的关系,通常一个应用使用一个base实例,所有实体类都应该继承此类对象

from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()

现在就可以创建一个domain类

from sqlalchemy import Column,Integer,Stringclass User(Base):__tablename__ = 'users'id = Column(Integer,primary_key=True)name = Column(String)fullname = Column(String)password = Column(String)   #这里的String可以指定长度,比如:String(20)def __init__(self,name,fullname,password):self.name = nameself.fullname = fullnameself.password = passworddef __repr(self):return "<User('%s','%s','%s')>"%(self.name,self.fullname,self.password)Base.metadata.create_all(engine)  

sqlalchemy 就是把Base子类转变为数据库表,定义好User类后,会生成Tablemapper(),分别通过User.__table__User.__mapper__返回这两个对象,对于主键,象oracle没有自增长的主键时,要使用:

from sqlalchemy import Sequence
Column(Integer,Sequence('user_idseq'),prmary_key=True)

Base.metadata返回sqlalchemy.schema.MetaData对象,它是所有Table对象的集合,调用create_all()该对象会触发CREATE TABLE语句,如果数据库还不存在这些表的话。

####创建Session

Session是真正与数据库通信的handler,你还可以把他理解一个容器,add就是往容器中添加对象

from sqlalchemy.orm import sessionmaker
Session = sessionmaker(bind=engine)#创建完session就可以添加数据了  
ed_user = User('ed','Ed jone','edpasswd')
session.add(ed_user)#也可以使用session.add_all()添加多个对象 
#session.add_all([user1,user2,user3])print ed_user in session  # True
session.rollback()
print ed_user in session # False

执行完add方法后,ed_user对象处于pending状态,不会触发INSERT语句,当然ed_uesr.id也为None,如果在add方后有查询(session.query),那么会flush一下,把数据刷一遍,把所有的pending信息先flush再执行query。

####对象状态
对象实例有四种状态,分别是:

  1. Transient(瞬时的):这个状态的对象还不在session中,也不会保存到数据库中,主键为None(不是绝对的,如果Persistent对象rollback后虽然主键id有值,但还是Transient状态的)。
  2. Pending(挂起的):调用session.add()后,Transient对象就会变成Pending,这个时候它还是不会保存到数据库中,只有等到触发了flush动作才会存在数据库,比如query操作就可以出发flush。同样这个时候的实例的主键一样为None
  3. Persistent(持久的):session中,数据库中都有对应的一条记录存在,主键有值了。
  4. Detached(游离的):数据库中有记录,但是session中不存在,对这个状态的对象进行操作时,不会触发任何SQL语句。

####查询
Query对象通过Session.query获取,query接收类或属性参数,以及多个类

for instance in session.query(User).order_by(User.id)print instance.namefor name,fullname in session.query(User.name,User.fullname):print name,fullname# TODO

filter_by接收的参数形式是关键字参数,而filter接收的参数是更加灵活的SQL表达式结构:

# sqlalchemy源码对filter_by的定义
def filter_by(self, **kwargs):
# 举例:
for user in session.query(User).filter_by(name=’ed’).all():print userfor user in session.query(User).filter(User.name==”ed”).all():print user

####常用过滤操作:

  • equals

      query.filter(User.name == 'ed')
    
  • not equal

      query.filter(User.name !='ed')
    
  • LIKE

      query.filter(User.name.like('%d%')
    
  • IN:

      query.filter(User.name.in_(['a','b','c'])
    
  • NOT IN:

      query.filter(~User.name.in_(['ed','x'])
    
  • IS NULL:

      filter(User.name==None)
    
  • IS NOT NULL:

      filter(User.name!=None)
    
  • AND

      from sqlalchemy import and_filter(and_(User.name == 'ed',User.fullname=='xxx'))    
    

    或者多次调用filter或filter_by

      filter(User.name =='ed').filter(User.fullname=='xx')
    

    还可以是:

      query.filter(User.name == ‘ed’, User.fullname == ‘Ed Jones’)
    
  • OR

      from sqlalchemy import or_query.filter(or_(User.name == ‘ed’, User.name == ‘wendy’))
    

对比一下Django:Django中ORM的filter方法里面只有一个等号,比如:

Entry.objects.all().filter(pub_date__year=2006)

#####查询返回结果

  • query.all(),all()返回列表
  • query.first():返回第一个元素
  • query.one()有且只有一个元素时才正确返回。

此外,filter函数还可以接收text对象,text是SQL查询语句的字面对象,比如:

for user in session.query(User).filter(text(“id<224”)).order_by(text(“id”)).all():print user.name

####count
有两种count,第一种是纯粹是执行SQL语句后返回有多少行,对应的函数count(),第二个是func.count(),适用在分组统计,比如按性别分组时,男的有多少,女的多少:

session.query(User).filter(User.name==’ed’).count()
session.query(func.count(), User.name).group_by(User.name).all( )

####Relattionship
SQLAlchemy中的映射关系有四种,分别是一对多,多对一,一对一,多对多
#####一对多(one to many)
因为外键(ForeignKey)始终定义在多的一方.如果relationship定义在多的一方,那就是多对一,一对多与多对一的区别在于其关联(relationship)的属性在多的一方还是一的一方,如果relationship定义在一的一方那就是一对多.
这里的例子中,一指的是Parent,一个parent有多个child.

class Parent(Base):__tablename__ = 'parent'id = Column(Integer,primary_key = True)children = relationship("Child",backref='parent')class Child(Base):__tablename__ = 'child'id = Column(Integer,primary_key = True)parent_id = Column(Integer,ForeignKey('parent.id'))

#####多对一(many to one)
这个例子中many是指parent了,意思是一个child可能有多个parent(父亲和母亲),这里的外键(child_id)和relationship(child)都定义在多(parent)的一方

class Parent(Base):__tablename__ = 'parent'id = Column(Integer, primary_key=True)child_id = Column(Integer, ForeignKey('child.id'))child = relationship("Child", backref="parents")class Child(Base):__tablename__ = 'child'id = Column(Integer, primary_key=True)

为了建立双向关系,可以在relationship()中设置backref(详情参考),Child对象就有parents属性.设置 cascade= 'all',可以级联删除

class Parent(Base):__tablename__ = 'parent'id = Column(Integer,primary_key = True)children = relationship("Child",cascade='all',backref='parent')def delete_parent():session = Session()parent = session.query(Parent).get(2)session.delete(parent)session.commit()

不过不设置cascade,删除parent时,其关联的chilren不会删除,只会把chilren关联的parent.id置为空,设置cascade后就可以级联删除children

#####一对一
一对一就是多对一和一对多的一个特例,只需在relationship加上一个参数uselist=False替换多的一端就是一对一:
从一对多转换到一对一:

class Parent(Base):__tablename__ = 'parent'id = Column(Integer, primary_key=True)child = relationship("Child", uselist=False, backref="parent")class Child(Base):__tablename__ = 'child'id = Column(Integer, primary_key=True)
parent_id = Column(Integer, ForeignKey('parent.id'))

从多对一转换到一对一:

class Parent(Base):__tablename__ = 'parent'id = Column(Integer, primary_key=True)child_id = Column(Integer, ForeignKey('child.id'))child = relationship("Child", backref=backref("parent", uselist=False))class Child(Base):__tablename__ = 'child'id = Column(Integer, primary_key=True)

#####多对多
多对多关系需要一个中间关联表,通过参数secondary来指定,

from sqlalchemy import Table,Text
post_keywords = Table('post_keywords',Base.metadata,Column('post_id',Integer,ForeignKey('posts.id')),Column('keyword_id',Integer,ForeignKey('keywords.id'))
)class BlogPost(Base):__tablename__ = 'posts'id = Column(Integer,primary_key=True)body = Column(Text)keywords = relationship('Keyword',secondary=post_keywords,backref='posts')class Keyword(Base):__tablename__ = 'keywords'id = Column(Integer,primary_key = True)keyword = Column(String(50),nullable=False,unique=True)

####关联查询(query with join)
简单地可以使用:
for u, a in session.query(User, Address).filter(User.idAddress.user_id).filter(Address.email’lzjun@qq.com’).all():
print u, a
如果是使用真正的关联SQL语法来查询可以使用:

session.query(User).join(Address).filter(Address.email==”lzjun@qq.com”).all()

因为这里的外键就一个,系统知道如何去关联
####relationship()API
relationship()函数接收的参数非常多,比如:backref,secondary,primaryjoin,等等。列举一下我用到的参数:

  • backref:在一对多或多对一之间建立双向关系,比如:

      class Parent(Base):__tablename__ = 'parent'id = Column(Integer, primary_key=True)children = relationship("Child", backref="parent")class Child(Base):__tablename__ = 'child'id = Column(Integer, primary_key=True)parent_id = Column(Integer, ForeignKey('parent.id'))
    

    Prarent对象获取children,parent.children,反过来Child对象可以获取parent:child.parent.

  • lazy:默认值是True,说明关联对象只有到真正访问的时候才会去查询数据库,比如有parent对象,只有知道访问parent.children的时候才做关联查询.

  • remote_side:表中的外键引用的是自身时,如Node类,如果想表示多对一的关系,那么就可以使用remote_side

      class Node(Base):__tablename__ = 'node'id = Column(Integer, primary_key=True)parent_id = Column(Integer, ForeignKey('node.id'))data = Column(String(50))parent = relationship("Node", remote_side=[id])
    

    如果是想建立一种双向的关系,那么还是结合backref:

      class Node(Base):__tablename__ = 'node'id = Column(Integer, primary_key=True)parent_id = Column(Integer, ForeignKey('node.id'))data = Column(String(50))children = relationship("Node",backref=backref('parent', remote_side=[id]))
    
  • primaryjoin:用在一对多或者多对一的关系中,默认情况连接条件就是主键与另一端的外键,用primaryjoin参数可以用来指定连接条件 ,比如:下面user的address必须现address是一’tony’开头:

      class User(Base):__tablename__ = 'user'id = Column(Integer, primary_key=True)name = Column(String)addresses = relationship("Address",primaryjoin="and_(User.id==Address.user_id, ""Address.email.startswith('tony'))",backref="user")class Address(Base):__tablename__ = 'address'id = Column(Integer, primary_key=True)email = Column(String)user_id = Column(Integer, ForeignKey('user.id'))
    
  • secondary:

  • order_by:
    在一对多的关系中,如下代码:

      class User(Base):# ....addresses = relationship("Address",order_by="desc(Address.email)",primaryjoin="Address.user_id==User.id")
    

    如果user的address要按照email排序,那么就可以在relationship中添加参数order_by.这里的参数是一字符串形式表示的,不过它等同于python表达式,其实还有另一种基于lambda的方式:

      class User(Base):# ...addresses = relationship(lambda: Address,order_by=lambda: desc(Address.email),primaryjoin=lambda: Address.user_id==User.id)
    

#####association_proxy
associationproxy是sqlalchemy扩展包里面的一个函数,是一个无关痛痒的提供便捷性的功能,在多的言语也不及官方文档的例子,还是看看文档吧.

#####column_propety
可以用column_property来实现SQL表达式作为映射类的属性(另外一种方式就是用hybrid),

对比Django中的ORM:
Django 中提供了三种通用的数据库关系类型,many-to-one,many-to-many,one-to-one,

many-to-one:
用ForeignKey来定义多对一的关系,假设一个员工只能隶属于一个部门,但部门可以有多个员工,则可以:

class Department(models.Model):...class Employee(models.Model):department = models.ForeignKey(Department)...

如果一个对象和自身有多对一的关系,则可以是:

models.ForeignKey('self'):class Employee(models.Model):manager = models.ForeignKey('self')

many-to-many:
用ManyToManyField来定义多对多的关系,假设Blog可以有多个Tag,一个Tag也可以在多篇Blog里面,那么就可以用ManyToManyField

class Blog(models.Model):tags = ManyToManyField(Tag)
class Tag(models.Model):....

同样可以通过ManyToManyField(‘self’)和自身建立多对多的关系.

one-to-one:
用OneToOneField来定义一对一的关系

相比较而言,django的orm可谓简单很多,但是性能方面未必优于sqlalchemy,不同点,sqlalchemy的model需要指定id,而django会自动帮你生成id.

####Session
Session 使用 connection发送query,把返回的result row 填充到一个object中,该对象同时还会保存在Session中,Session内部有一个叫 Identity Map的数据结构,为每一个对象维持了唯一的副本。primary key 作为 key ,value就是该object。
session刚开始无状态,直到有query发起时。

对象的变化会被session的跟踪维持着,在数据库做下一次查询后者当前的事务已经提交了时,it fushed all pendings changes to the database.
这就是传说中的 Unit of work 模式

例如:

def unit_of_work():session = Session()album = session.query(Album).get(4)album.name = "jun"   #这里不会修改album的name属性,不会触发update语句def unit_of_work():session = Session()album = session.query(Album).get(4)album.name = "jun"   #这里修改了album的name属性,会触发一个update语句session.query(Artist).get(11)session.commit()

####构造了session,何时commit,何时close
规则:始终保持session与function和objecct分离

####transaction scope 和 session scope

#####对象的四种状态
对象在session中可能存在的四种状态包括:

  • Transient :实例还不在session中,还没有保存到数据库中去,没有数据库身份,想刚创建出来的对象比如User(),仅仅只有mapper()与之关联
  • Pending :用add()一个transient对象后,就变成了一个pending对象,这时候仍然没有flushed到数据库中去,直到flush发生。
  • Persistent :实例出现在session中而且在数据库中也有记录了,通常是通过flush一个pending实例变成Persistent或者从数据库中querying一个已经存在的实例。
  • Detached:一个对象它有记录在数据库中,但是不在任何session中,
Hibernate中的Session

SessionFactory创建Session,SessionFactory是线程安全的,而Session是线程不安全的。Session是轻量级的,创建和删除都不需要耗太大的资源,这与JDBC的connection不一样,Connection的创建时很好资源的。
Session对象内部有一个缓存,称之为Hibernate第一级缓存,每个session实例都有自己的缓存,存放的对象是当前工作单元中加载的对象。
Hibernate Session 缓存三大作用:

  1. 减少数据库的访问频率,提高访问性能
  2. 保证缓存的对象与数据库同步,位于缓存中的对象称为持久化对象
  3. 当持久化对象存在关联时,session保证不出现对象图的死锁

####Session什么时候清理缓存

  1. commit()方法调用的时候
  2. 查询时会清理缓存,保证查询结果能反映对象的最新状态
  3. 显示调用session的flush方法

####Querying

q = session.query(SomeMappedClass)

session的query方法就可以创建一个查询对象,

def add_before_query():session = Session()ed_user = User(name='zhangsan')session.add(ed_user)user = session.query(User).filter_by(name='zhangsan').first()print ed_user == user

这里的ed_user == user 返回True,session中会根据用主键作为key,object作为vlaue缓存在session中

def test1():session = Session()jack = session.query(User).filter_by(name='lzjun').one()print jackprint jack.addresses

默认sqlalchemy 使用的时懒加载的模式,查询user的时候,并不会查询user.addresses,只有真正使用user.addresses的时候
才会触发user.addresses的查询语句。

from sqlalchemy.orm import subqueryload
def subquery_load_test():session = Session()jack = session.query(User).\options(subqueryload(User.addresses)).\filter_by(name='lzjun').one()print jack

使用subqueryload操作,饿汉式加载,查询user的时候,就把addresses查询出来了。

####传统映射
用Table构建一个table metadata,然后通过映射函数mapper与User关联起来

from sqlalchemy import Table,Metadata
metadata = Metadata()user = Table('user',metadata,Column('id',Integer,primary_key = True),)
class User(object):def __init__(self,name):self.name = name
mapper(User,user)

等价于:

class User(Base):id = Column(Integer,primary_key = True)name = Column(String)def __init__(self,name):self.name = name

###使用加载策略(懒加载,饿加载)
SQLAlchemy 默认使用 Lazy Loading 策略加载对象的 relationships。因此,如果你在对象 detached 之后访问对象的 relationships,会报 “DetachedInstanceError” 错误。例如:

user = session.query(User).get(id)
_session.close()
print user.comments # this will raise DetachedInstanceError
如果你需要在对象 detach 后访问 relationships(例如需要跨进程共享对象),则应该使用 Eager Loading 策略:

session.query(User).options(joinedload(‘comments’)).get(id)
_session.close()
print user.comments # OK
如果需要加载所有的 relationships ,可以设置 Default Loading Strategies :

class Parent(Base):__tablename__ = 'parent'id = Column(Integer,primary_key = True)children = relationship("Child",backref='parent')class Child(Base):__tablename__ = 'child'id = Column(Integer,primary_key = True)parent_id = Column(Integer,ForeignKey('parent.id'))

在one的那端设置了backref后,反过来就是多对一,在保存child时不需要显示的保存parent

def save_child():parent = Parent()child1 = Child(parent = parent)child2 = Child(parent = parent)child3 = Child(parent = parent)session = Session()session.add_all([child1,child2,child3])session.flush()session.commit()

设置 cascade= 'all',可以级联删除

class Parent(Base):__tablename__ = 'parent'id = Column(Integer,primary_key = True)children = relationship("Child",cascade='all',backref='parent')def delete_parent():session = Session()parent = session.query(Parent).get(2)session.delete(parent)session.commit()

不过不设置cascade,删除parent时,其关联的chilren不会删除,只会把chilren关联的parent.id置为空,设置cascade后就可以级联删除children

####Session
Session 使用 connection发送query,把返回的result row 填充到一个object中,该对象同时还会保存在Session中,Session内部有一个叫 Identity Map的数据结构,为每一个对象维持了唯一的副本。primary key 作为 key ,value就是该object。
session刚开始无状态,直到有query发起时。

对象的变化会被session的跟踪维持着,在数据库做下一次查询后者当前的事务已经提交了时,it fushed all pendings changes to the database.
这就是传说中的 Unit of work 模式

例如:

def unit_of_work():session = Session()album = session.query(Album).get(4)album.name = "jun"   #这里不会修改album的name属性,不会触发update语句def unit_of_work():session = Session()album = session.query(Album).get(4)album.name = "jun"   #这里修改了album的name属性,会触发一个update语句session.query(Artist).get(11)session.commit()

####构造了session,何时commit,何时close
规则:始终保持session与function和objecct分离

####transaction scope 和 session scope

#####对象的四种状态
对象在session中可能存在的四种状态包括:

  • Transient :实例还不在session中,还没有保存到数据库中去,没有数据库身份,想刚创建出来的对象比如User(),仅仅只有mapper()与之关联
  • Pending :用add()一个transient对象后,就变成了一个pending对象,这时候仍然没有flushed到数据库中去,直到flush发生。
  • Persistent :实例出现在session中而且在数据库中也有记录了,通常是通过flush一个pending实例变成Persistent或者从数据库中querying一个已经存在的实例。
  • Detached:一个对象它有记录在数据库中,但是不在任何session中,
Hibernate中的Session

SessionFactory创建Session,SessionFactory是线程安全的,而Session是线程不安全的。Session是轻量级的,创建和删除都不需要耗太大的资源,这与JDBC的connection不一样,Connection的创建时很好资源的。
Session对象内部有一个缓存,称之为Hibernate第一级缓存,每个session实例都有自己的缓存,存放的对象是当前工作单元中加载的对象。
Hibernate Session 缓存三大作用:

  1. 减少数据库的访问频率,提高访问性能
  2. 保证缓存的对象与数据库同步,位于缓存中的对象称为持久化对象
  3. 当持久化对象存在关联时,session保证不出现对象图的死锁

####Session什么时候清理缓存

  1. commit()方法调用的时候
  2. 查询时会清理缓存,保证查询结果能反映对象的最新状态
  3. 显示调用session的flush方法

session.query(User).options(joinedload(’*’)).get(id)
_session.close()
print user.comments # OK
print user.posts # OK

####Relattionship

#####一对多 (one to many)

mapping class link to table metadata

print session.query(func.count(User.id)).all()
print session.query(func.count(User.id)).first()
print session.query(func.count(User.id)).scalar()all()返回的是list,[(10,)]
first()返回的是tuple,(10,),就是all()里面的的第0个元组
scalar()返回的就是单一值,元组中的第0个值,而且scalar只使用于当前返回的是单个值,比如all()里面返回的10

####Classic mapping

from sqlalchemy import Table, MetaData
from sqlalchemy.orm import mapper
metadata = MetaData()
subject = Table('subject', metadata,Column('id', Integer, primary_key=True),Column('title', String(100)))
class Subject(object):def __init__(self, name):self.name = name
metadata.create_all(engine)  #生成数据库表
mapper(Subject,subject)   #建立映射

####Hybrid Attributes 混合属性
属性在类和实例上有特殊的行为

from sqlalchemy import Column, Integer
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import Session, aliased
from sqlalchemy.ext.hybrid import hybrid_property, hybrid_methodBase = declarative_base()class Interval(Base):__tablename__ = 'interval'id = Column(Integer, primary_key=True)start = Column(Integer, nullable=False)end = Column(Integer, nullable=False)def __init__(self, start, end):self.start = startself.end = end@hybrid_propertydef length(self):print selfreturn self.end - self.start@hybrid_methoddef contains(self,point):return (self.start <= point) & (point < self.end)@hybrid_methoddef intersects(self, other):return self.contains(other.start) | self.contains(other.end)

这个hybrid_property和python中的@property有什么区别呢?区别就在这个hybrid上,既然是混合的属性,也就是说,既可以作为实例属性
也可以作为类属性,

if __name__ == '__main__':Base.metadata.create_all(engine)i = Interval(5, 10)print i.lengthprint Interval.length

输出结果是:

<__main__.Interval object at 0x9cfdd8c> ----
5
<class '__main__.Interval'> ----
interval."end" - interval.start

而Interval.length的type是

<class 'sqlalchemy.sql.expression.BinaryExpression'>

那它有什么用呢?

Session().query(Interval).filter(Interval.length > 10)

它的用法看起来跟属性start、end一样的,而你却无需在数据库中像start、end一样定义一个字段,多好。

那@hibrid_method有什么用呢? ,如果是判断point是不是contains,直接:

i.contains(7) 

就好了啊,干嘛要用@hibrid_method呢?

Session().query(Interval).filter(Interval.contains(15))

看到了吧,和hybrid_property有相似之处

####区别于属性的表达式装饰器

from sqlalchemy import funcclass Interval(object):# ...@hybrid_propertydef radius(self):return abs(self.length) / 2@radius.expressiondef radius(cls):return func.abs(cls.length) / 2

这里为什么还要用radius.expression呢,对于查询:

Session().query(Interval).filter(Interval.radius > 5)

直接像length一样不行吗?当然不行,不信,注释掉radius.expression试试。

TypeError: bad operand type for abs(): 'BinaryExpression'

其实它接收的是一个sqlahclemy里面的函数,func.abs,因为这里面使用的length也是一个hybrid的属性

@length.setter
def length(self, value):self.end = self.start + value

也支持setter

####mapping class inheritance hierarchies

使用memecache做缓存的时候,出现了错误:读取一篇article,异常信息:

DetachedInstanceError: Parent instance <Article at 0xb22da4c> is not bound to a Session; lazy load operation of attribute 'user' cannot proceed

访问代码:

 session = DBSession()@cache_region('long_term')def func_to_cache(session):article = session.query(Article).get(articleId)return articlearticle = func_to_cache(session)

这段代码的意思相当于:

article = mc.get(key)
if not article:article = session.query(Article).get(articleid)mc.set(key, article)

因为Article类还关联了user

userId = Column('user_id', IdDataType, ForeignKey('user_profile.user_id'), nullable=False)
user = relationship(UserProfile)

默认SQLAlchemy的实体是使用Lazyload模式,也就是说只有真正访问article.user的时候才会去数据库查询该用户,而这里事先把article缓存起来了,在访问article的时候延迟查询所使用的session跟原对象的关联被切断了。没法触发sql查询了。可以使用 eager loading,通过joinedload(),
http://docs.sqlalchemy.org/en/latest/orm/inheritance.html
http://docs.sqlalchemy.org/en/latest/orm/loading.html

####错误总结:
1.用column_property()函数做为类属性的时候:

Article.recommendCnt = column_property(select([func.count(ArticlePGoal.id)]).where(and_( Article.id == ArticlePGoal.articleId, ArticlePGoal.artType == ArticlePGoal.ART_TYPE_RECOMMEND, Article.id == ArticlePGoal.articleId, ~Article.isDeleted)))  

抛出的异常:

InvalidRequestError: Select statement 'SELECT count(article_pgoal.id) AS count_1 
FROM article_pgoal, article 
WHERE article.id = article_pgoal.article_id AND article_pgoal.art_type = %s AND article.id = article_pgoal.article_id AND NOT article.is_deleted' returned no FROM clauses due to auto-correlation; specify correlate(<tables>) to control correlation manually.

关键看错误信息的最后一句,它告诉我们需要手动指定关联的表

Article.recommendCnt = column_property(select([func.count(ArticlePGoal.id)]).where(and_( Article.id == ArticlePGoal.articleId, ArticlePGoal.artType == ArticlePGoal.ART_TYPE_RECOMMEND, Article.id == ArticlePGoal.articleId, ~Article.isDeleted)).correlate(Article.__table__))
  1. 使用memecache做缓存的时候,异常:

    DetachedInstanceError: Instance <Article at 0xb3b239ec> is not bound to a Session; attribute refresh operation cannot proceed

可以设置 session.expire_on_commit = False

####列与数据类型
http://docs.sqlalchemy.org/en/rel_0_9/core/types.html
BigInteger对应数据库中的BIGINT
Boolean对应BOOLEAN或SAMLLINT,Python端是True或False
Date对应datetime.date()对象
DateTime就是datetime.datetime()对象
Float
Integer
Interval对应datetime.timedelta(),在数据库中如果是PostgreSQL对应本地的INTERVAL类型,其它数据库用date保存.(相对于1970,1,1)
Text继承自String,在SQL中使用CLOB或TEXT,一般没有长度
Time datetime.time()
Unicode继承String,有length参数
UnicodeText

####映射类继承层次
SQLAlchemy支持三种形式的继承,单表继承, 多个类对应单独的一个表,具体表继承:

####Querying
http://docs.sqlalchemy.org/en/rel_0_9/orm/query.html#sqlalchemy.orm.query.Query.join

相关文章:

SQLAlchemy 学习笔记

通信类型&#xff1a;AF_INET 协议家族一般是表示TCP通信的SOC_STREAM和UDP通信的SOCK_DGRAM。对于TCP通信&#xff0c;建立socket连接&#xff0c;&#xff1a; s socket.socket(socket.AF_INET, socket.SOCK_STREAM)连接socket&#xff0c; s.connect((host,port))socket通信…...

Linux内核分析(调度类和调度实体)

文章目录 前言一、调度类1. stop_sched_class2. dl_sched_class3. rt_sched_class4. fair_sched_class5. idle_sched_class总结 二、调度类中的操作函数三、调度实体 前言 调度是操作系统内核的一个关键职责&#xff0c;它涉及到如何合理分配CPU时间给不同的进程或线程。在Lin…...

用输入输出流(I/O)流,递归复制和删除多级文件

一、&#xff08;I/O&#xff09;流递归复制一个文件 第一种&#xff1a; else if语句过多&#xff0c;看起来冗余&#xff0c;优点&#xff1a;多级文件一次性复制完整 import java.io.*;//数据源&#xff1a;src/main/java/day15_8_13/haha //目标;src/main/java/LaJi pub…...

kafka监控工具EFAK

kafka监控工具&#xff08;EFAK&#xff09; 1、下载2、解压3、配置3.1、安装数据库&#xff0c;需要mysql是&#xff0c;并创建ke数据库3.2、修改配置文件 4、启动4.1、启动zookeeper4.2、启动kafka4.3、启动EFAK 5、访问http://ip:8048 github地址&#xff1a;https://github…...

Page与自定义Components生命周期

自定义组件 自定义组件一般可以用component,装饰&#xff0c;在结构体里面用build方法定义UI,或者用builder装饰一个方法&#xff0c;来作为自定义组件的构造方法 而页面page一般用Entry,和component结合起来使用 页面生命周期方法: onPageShow:页面每次显示时触发 onPageHid…...

Chain of Thought (CoT) 系列论文:大模型思维链,提升 LLM 的推理能力

文章目录 1. COT&#xff1a;Chain of Thought1. 研究背景2. CoT的原理3. CoT Prompt 1. COT&#xff1a;Chain of Thought COT 是 2022.01 由 google 提出的针对提升 LLM 的推理能力的 Prompt Engineering 方法。 paper&#xff1a; Chain-of-Thought Prompting Elicits Re…...

已解决:java.net.BindException: 地址已在使用

1. 问题描述 java.net.BindException: 地址已在使用 是一种常见的网络异常&#xff0c;通常在服务器程序尝试绑定到一个已经被占用的端口或地址时出现。具体的异常信息可能如下&#xff1a; java.net.BindException: Address already in use: JVM_Bind或 java.net.BindExcep…...

看书标记【数据科学:R语言实战 8】

看书标记——R语言 Chapter 8 数据可视化——绘图8.1 功能包8.2 散点图8.2.1 回归线8.2.2 lowess线条8.2.3 scatterplot函数8.2.4 Scatterplot矩阵1.splom——展示矩阵数据2.cpairs——绘图矩阵图 8.2.5 密度散点图 8.3 直方图和条形图8.3.1 条形图8.3.2 直方图 8.3.3 ggplot28…...

STM32标准库学习笔记-1.基础知识

STM32介绍&#xff1a; STM32是ST公司基于ARM Cortex-M内核开发的32位微控制器。 ARM的含义&#xff1a; 公司名称&#xff1a;ARM公司成立于1990年&#xff0c;全称是Advanced RISC Machines&#xff08;RISC:Reduced Instruction Set Computer 精简指令集计算机 相对应有C…...

Nginx:高效HTTP服务器与反向代理

Nginx&#xff1a;高效HTTP服务器与反向代理 1、核心特点2、应用场景 &#x1f496;The Begin&#x1f496;点点关注&#xff0c;收藏不迷路&#x1f496; Nginx&#xff0c;一个开源的HTTP服务器与反向代理工具&#xff0c;因其高性能、低资源消耗而备受推崇。以下是Nginx的几…...

vue3二次封装element-puls

将表单的通用信息给设置出来 如: label 的提示信息 , type 的类型 // 定义表单的配置项 const formConfig{ formItems:[ { type:"input", label:"用户ID", placeholder:"请输入用户ID" } ] } 页面配置如 <template v-for"(it…...

在CentOS 7上安装Apache Tomcat 8的方法

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站。 介绍 Apache Tomcat 是一个用于提供 Java 应用程序的 Web 服务器和 Servlet 容器。Tomcat 是由 Apache 软件基金会发布的 Java Servlet…...

深入理解分布式事务中的三阶段提交(3PC),什么是3PC,3PC原理是怎样?3PC的优化?

在上一篇文章中&#xff0c;我们详细介绍了分布式事务中的两阶段提交&#xff0c;以及知道了两阶段提交存在一定的问题 深入理解分布式事务中的两阶段提交&#xff08;2PC&#xff09;&#xff0c;什么是2PC&#xff0c;2PC原理是怎样&#xff1f;2PC有没有什么问题&#xff1…...

这款新的 AI 工具会消灭 ChatGPT 吗?

随着大型语言模型 (LLM) 的出现&#xff0c;ChatGPT迅速成为全球计算机用户的家喻户晓的名字。这款由 OpenAI 设计的深度学习聊天机器人以知识宝库而闻名——一部互联网百科全书。 继ChatGPT的脚步之后&#xff0c;许多其他生成式AI工具也纷纷涌现。 2023 年 3 月&#xff0c;一…...

谷粒商城实战笔记-214~219-商城业务-认证服务-验证码防刷校验

文章目录 一&#xff0c;验证码防刷校验1&#xff0c;第三方服务提供发送短信的接口2&#xff0c;登录服务提供给前端的接口 二&#xff0c;215-商城业务-认证服务-一步一坑的注册页环境三&#xff0c;商城业务-认证服务-异常机制四&#xff0c;217-商城业务-认证服务-MD5&…...

在华为服务器的openEuler系统中适配Pytorch调用NPU

服务器架构&#xff1a;aarch64 yolov7 和 mindyolo 二选一即可&#xff0c;yolov7是基于pytorch&#xff0c;mindyolo是基于mindspore 本文档基于CANN8.0RC3 , 刚发布比较新&#xff0c;如果有问题&#xff0c;可将CANN版本降低 导读 资料首页&#xff1a;https://www.hiasce…...

MVCC工作原理深入解析

一、事务概述 mysql事务是指一组命令操作&#xff0c;在执行过程中用来保证要么全部成功&#xff0c;要么全部失败。事务是由引擎层面来支持的&#xff0c;MyISM引擎不支持事务&#xff0c;InnoDB引擎支持事务。 事务具有ACID四大特性 原子性&#xff08;Atomicity&#xff0…...

使用html+css+js实现完整的登录注册页面

在这篇博客中&#xff0c;我们将讨论如何使用简单的 HTML 和 CSS 构建一个登录与注册页面。这个页面包含两个主要部分&#xff1a;登录界面和注册界面。我们还会展示如何通过 JavaScript 切换这两个部分的显示状态。 页面结构 我们将创建一个页面&#xff0c;其中包含两个主要…...

2024年8月16日(运维自动化 ansible)

一、回顾 1、mysql和python (1)mysql5.7 1.1不需要执行mysql_ssl_rsa_setup 1.2change_master_to 不需要get public key (2)可以使用pymysql非交互的管理mysql 2.1pymysql.connect(host,user,password,database,port) 2.2 cursorconn.cursor() 2.3 cursor.execute("creat…...

荣耀Magicbook x14 扩容1TB固态

版权归作者所有&#xff0c;如有转发&#xff0c;请注明文章出处&#xff1a;https://cyrus-studio.github.io/blog/ 固态硬盘规格 在官网查看加装固态硬盘的接口规格 https://www.honor.com/cn/laptops/honor-magicbook-x14-2023/ https://club.honor.com/cn/thread-2847379…...

Springboot整合全文检索引擎Lucene

文章目录 前言Lucene的介绍springboot项目中如何整合Lucene简单用法1. 引入依赖2. 其它用到的类2. 创建索引3. 简单搜索4. 更新索引5. 删除索引6. 删除全部索引 Springboot整合Lucene复杂搜索1. 同时标题和内容中查找关键词2. 搜索结果高亮显示关键词3. 分页搜索4. 多关键词联合…...

【深度学习】【语音】TTS, 如何使用Python分析WAV的采样率、比特深度、通道数

文章目录 使用Python分析WAV文件的属性与可视化简介所需环境代码解析可视化音频数据结论使用Python分析WAV文件的属性与可视化 WAV文件录音要求 为了确保录制的音频文件符合TTS模型训练的质量标准,请遵循以下录音要求: 采样率要求:44.1 kHz说明:采样率44.1 kHz(即每秒采样…...

Linux的安装和使用

Linux 第一节 Linux 优势 1. 开源 为什么这么多的的设备都选择使用 Linux&#xff1f;因为它是开源软件&#xff08;open source software&#xff09;&#xff0c;具有不同的含义。使用一个安全的操作系统工作变得必不可少的事&#xff0c;而 Linux 恰好满足了这个需求。因…...

查看一个exe\dll文件的依赖项

方法 使用一个Dependencies工具&#xff0c;检测exe文件的所有依赖项 工具使用 下载压缩包之后解压&#xff0c;解压后如下图所示 在命令行中运行Dependencies.exe程序会得到帮助菜单 查询某exe的所有依赖项&#xff0c;使用命令 Dependencies.exe -chain <查询文件> …...

高校科研信息管理系统pf

TOC springboot364高校科研信息管理系统pf 第1章 绪论 1.1 研究背景 互联网概念的产生到如今的蓬勃发展&#xff0c;用了短短的几十年时间就风靡全球&#xff0c;使得全球各个行业都进行了互联网的改造升级&#xff0c;标志着互联网浪潮的来临。在这个新的时代&#xff0c;…...

Linux 开机自动挂载共享文件设置

选择一个要共享的文件 点击确定 -> 确定 启动虚拟机 执行下面的命令 /YumSource 是我选择的共享文件夹&#xff0c;自行替换自已选择的文件夹 mkdir -p /mnt/hgfs cat >> /etc/fstab << EOF .host:/YumSource /mnt/hgfs fuse.vmhgfs-fuse allow_other defaul…...

c_cpp_properties.json、launch.json、 tasks.json

在 Visual Studio Code 中&#xff0c;c_cpp_properties.json、launch.json 和 tasks.json 是三个重要的配置文件&#xff0c;它们的作用如下&#xff1a; c_cpp_properties.json&#xff1a; 这个文件用于配置 C/C 扩展的 IntelliSense、编译器路径和包括路径等。它帮助 VS Co…...

mysql 一些知识点 面试用

mysql 1、4个隔离级别与3个现象2、快照读与当前读2.1 可重复读的情况下出现幻读问题的两种情况 3 数据库 常用引擎4、InnoDB存储引擎对MVCC的实现5、索引(重点)5.1 什么是索引5.2 索引的创建与删除5.2.1 查看表中有哪些索引5.2.2 添加索引5.2.3 删除索引 5.3 索引的分类5.4 树数…...

STM32之点亮LED灯

使用固件库实现LED点灯 LED灯&#xff1a; LED灯&#xff0c;是一种能够将电能转化为可见光的半导体器件 控制LED灯&#xff1a; LED灯的正极接到了3.3V&#xff0c;LED灯的负极接到了PA1&#xff0c;也就是GPIOA1引脚 只需要控制PA1为相对应的低电平&#xff0c;即可点亮对…...

Java 多线程练习2 (抽奖比较Runnable写法)

MultiProcessingExercise2 package MultiProcessingExercise120240814;import java.util.ArrayList; import java.util.Collections;public class MultiProcessingExercise1 {public static void main(String[] args) {// 需求&#xff1a;// 在此次抽奖过程中&#xff0c;抽奖…...

使用fastboot更新部分系统

使用fastboot更新部分系统 获取分区信息 > part list sunxi_flash 0Partition Map for UNKNOWN device 0 -- Partition Type: EFIPart Start LBA End LBA NameAttributesType GUIDPartition GUID1 0x00008000 0x000097c5 "boot-r…...

windows 加载portch遇到的错误

import torch 遇到如下错误 File "<stdin>", line 1, in <module> File "C:\Users\Administrator\AppData\Local\Programs\Python\Python311\Lib\site-packages\torch\__init__.py", line 148, in <module> raise err OSError: [W…...

如何将 CICD 模版重构为 CICD component?

极狐GitLab 是 GitLab 在中国的发行版&#xff0c;专门面向中国程序员和企业提供企业级一体化 DevOps 平台&#xff0c;用来帮助用户实现需求管理、源代码托管、CI/CD、安全合规&#xff0c;而且所有的操作都是在一个平台上进行&#xff0c;省事省心省钱。可以一键安装极狐GitL…...

数学建模——评价决策类算法(层次分析法、Topsis)

一、层次分析法 概念原理 通过相互比较确定各准则对于目标的权重, 及各方案对于每一准则的权重&#xff0c;这些权重在人的思维过程中通常是定性的, 而在层次分析法中则要给出得到权重的定量方法. 将方案层对准则层的权重及准则层对目标层的权重进行综合, 最终确定方案层对目标…...

KEEPALIVED 全csdn最详细----理论+实验(干货扎实,包教会的)

环境准备 主机名IP虚拟IP&#xff08;VIP&#xff09;功能ka1172.25.254.10172.25.254.100keepalived服务ka2172.25.254.20172.25.254.100keepalived服务realserver1172.25.254.110web服务realserver2172.25.254.120web服务 注意一定要关闭selinux,和防火墙&#xff0c;不然在…...

微信云开发云存储全部下载

一、安装 首先按照这个按照好依赖 安装 | 云开发 CloudBase - 一站式后端云服务 npm i -g cloudbase/cli 二、登录 tcb login 下载 首先在你要下载到的本地文件内创建一个名为&#xff1a;cloudbaserc.json 的json文件。 填入你的id {"envId":"你的云开发环…...

vos3000怎样对接voip落地语音网关呢?卡机和O口网关的配置技巧有哪些?

很多朋友没有接触过vos系统的使用&#xff0c;那么vos3000如何对接voip落地网关呢&#xff1f;卡机的配置技巧有哪些&#xff1f; VOS3000系统是针对中小等规模VoIP运营业务提供的支撑系统。 语音网关 落地网关分O口网关&#xff0c;S口网关&#xff0c;和全网通GOIP语音网关。…...

MySQL数据库专栏(四)数据库操作

1、创建数据库 create database if not exists [数据库名称] character set [字符集] COLLATE [排序规则]; 例如&#xff1a;create database if not exists db_demo character set utf8mb4 COLLATE utf8mb4_general_ci; if not exists&#xff1a;判断数据库是否存在&#x…...

Python编写Word文档

目录 0. 安装依赖 1. 创建word文档 2. 添加标题、居中、字体16大小 3. 添加标题一 4. 添加一段话并设置字体颜色 封装函数 5. 换页 6. 插入表格 0. 安装依赖 python-docx1.1.2 1. 创建word文档 from docx import Documentdoc Document() 2. 添加标题、居中、字体1…...

聚星文社AI工具

聚星文社AI工具是一款基于人工智能技术的文学创作辅助工具。聚星文社AI工具https://docs.qq.com/doc/DRU1vcUZlanBKR2xy 它能够帮助作者生成文字内容、自动校对、提供创作灵感等功能。 通过聚星文社AI工具&#xff0c; 作者可以更快速地完成文学作品的创作&#xff0c;提高创…...

思科OSPF动态路由配置8

#路由协议实现# #任务八OSPF动态路由配置8# 开放式最短路径优先&#xff08;Open Shortest Path First,OSPF&#xff09;协议是目前网络中应用最广泛的动态路由协议之一。它也属于内部网关路由协议&#xff0c;能够适应各种规模的网络环境&#xff0c;是典型的链路状态路由协…...

C++(10)类语法分析(1)

C(10)之类语法分析(1) Author: Once Day Date: 2024年8月17日 一位热衷于Linux学习和开发的菜鸟&#xff0c;试图谱写一场冒险之旅&#xff0c;也许终点只是一场白日梦… 漫漫长路&#xff0c;有人对你微笑过嘛… 全系列文章可参考专栏: 源码分析_Once-Day的博客-CSDN博客 …...

python语言day6 os random datetime .ini文件

os&#xff1a; 获取运行当前py文件的绝对路径&#xff1a; abspath中添加路径&#xff0c;会直接和绝对路径拼接。 folder_path os.path.abspath("") print(folder_path) 路径拼接&#xff1a; mac系统路径&#xff1a;file/TranslucentTB win系统路径&#xff1a;…...

powershell 终端 执行 pnpm -v报错

1.问题描述&#xff1a; 明明全局已安装 pnpm &#xff0c;但在vscode默认终端 powershell 执行 pnpm -v 却报错&#xff1a; 2.问题根因&#xff1a; 原因是 PowerShell 执行策略问题。 3.解决方案&#xff1a; 以管理员身份运行 PowerShell 查看 PowerShell 的执行策略…...

最新保姆级Anaconda和Pycharm安装激活过程(2024最新版本)

Anaconda和Pycharm安装过程 Anaconda安装过程第一步第二步第三步第四步第五步第六步第七步第八步第九步Pycharm 安装过程&#xff1a;第一步第二步第三步第四步第五步第六步---激活过程第七步第八步第九步第十步第十一步第十二步第十三步第十四步Anaconda和Pycharm软件百度网盘…...

虚幻5|布料模拟

打开骨骼网格体 1.Mass Prooerties 如果给角色施加风力&#xff0c;密度越大越难飘&#xff0c;相反密度越小飘动浮度也小 2.Material Proerties Edge Stiffness,对衣服的折痕处的调整&#xff0c;其值越大就越能维持原本的折痕&#xff0c;相反折痕就会变小&#xff0c;但…...

K8S 存储

K8S&#xff08;Kubernetes&#xff09;的存储是容器化应用程序中非常重要的一部分&#xff0c;它帮助用户在不同场景下管理和存储数据。K8S提供了多种存储方式&#xff0c;以满足不同的存储需求。以下是对K8S存储的详细解析&#xff1a; 一、K8S存储类型 K8S的存储类型主要分…...

Kafka Manager支持jdk1.8的部署和使用

一、Kafka Manager简介 Kafka Manager 可能是现在能找到的最好的可视化的Kafka管理工具, 感谢Yahoo的开源; 使用Kafka Manager, 基本上之前需要运行Kafka相应命令行工具的工作现在都可以可视化的完成:创建Topic, 调整消息保存时长, Partition数量等等配置;管理Topic, 包括Reas…...

vmware和virtualbox优缺点

vmware和virtualbox优缺点 &#xff0c;都可以搭建本地虚拟机&#xff0c;他们有什么优缺点&#xff0c;两个都用过 &#xff0c;本次打算直接用virtualbox搭建本地虚拟机&#xff0c;比较轻量级 VirtualBox的优点&#xff1a; 免费使用&#xff1a;VirtualBox是一…...

[C++进阶]二叉树进阶的一些面试题(一)

首先我们先回忆我们过去学的二叉树和最近学的二叉搜索树,来完成下面的题目: 606. 根据二叉树创建字符串 这道题属于与基础题,首先我们观察输入输出样例可以得到如果root->left为空,root->right不为空时,我们的空格仍然需要保留,如果当前节点有两个孩子&#xff0c;那我…...