In [5]:
from model.db.tb_raw import TbRaw
query = TbRaw.select().where(TbRaw.id > 0)
print "select query:", query.sql()[0] % tuple(query.sql()[1])
print "query result:"
for item in query.dicts().execute():
print item
其中Tb1
是我们定义的一个Model
class TbRaw(Model):
"""
"""
id = PrimaryKeyField()
name = CharField()
age = IntegerField()
create_time = DateTimeField()
class Meta(object):
"""表配置信息
"""
database = MySQLDatabase(database="xyz", host="127.0.0.1", password="123456", user="root", port=3306)
db_table = "tb_raw"
peewee对Model
类指定BaseModel
元类
class Model(with_metaclass(BaseModel)):
而BaseModel
中做的就是将TbRaw的配置信息转换成一个ModelOptions
对象放到_meta
中,其中包括数据库连接、字段信息、主键、表明、索引等。因为_meta
是在元类中生成,所以Model表的配置信息不能针对实例做修改,而是一个整体的修改。这里对于做分表查询不能很好的支持。
Model
中提供了SQL中的数据查询、操作、定义的类方法,对应方法返回的对象如下。
@classmethod
def select(cls, *selection):
query = SelectQuery(cls, *selection)
if cls._meta.order_by:
query = query.order_by(*cls._meta.order_by)
return query
select()
方法返回一个SelectQuery
对象,并将排序字段传递进去。
SelectQuery
中提供保留的查询方法(group_by、having、order_by、window、limit、offset、paginate、distinct、where等)
这些查询方法通过修饰器@returns_clone
每一次返回一个新的SelectQuery
对象。
def returns_clone(func):
"""
Method decorator that will "clone" the object before applying the given
method. This ensures that state is mutated in a more predictable fashion,
and promotes the use of method-chaining.
"""
def inner(self, *args, **kwargs):
clone = self.clone() # Assumes object implements `clone`.
func(clone, *args, **kwargs)
return clone
inner.call_local = func # Provide a way to call without cloning.
return inner
return_clone
首先会调用Query
中的clone()
方法,然后执行相应的保留查询方法。
def clone(self):
query = type(self)(self.model_class)
query.database = self.database
return self._clone_attributes(query)
clone()
方法会生成一个新的SelectQuery
对象,然后复用数据库连接,克隆原Query实例中的对象。
In [6]:
# UNION查询
query = TbRaw.select().where(TbRaw.id >= 2) | TbRaw.select().where(TbRaw.id < 2)
print query.sql()[0] % tuple(query.sql()[1])
for item in query.dicts().execute():
print item
在SelectQuery
中通过重载运算符实现UNION(并集)、INTERSECT(交集)、EXCEPT(差集)语句。
def compound_op(operator):
def inner(self, other):
supported_ops = self.model_class._meta.database.compound_operations
if operator not in supported_ops:
raise ValueError(
'Your database does not support %s' % operator)
return CompoundSelect(self.model_class, self, operator, other)
return inner
_compound_op_static = staticmethod(compound_op)
__or__ = compound_op('UNION')
__and__ = compound_op('INTERSECT')
__sub__ = compound_op('EXCEPT')
def __xor__(self, rhs):
# Symmetric difference, should just be (self | rhs) - (self & rhs)...
wrapped_rhs = self.model_class.select(SQL('*')).from_(
EnclosedClause((self & rhs)).alias('_')).order_by()
return (self | rhs) - wrapped_rhs
def union_all(self, rhs):
return SelectQuery._compound_op_static('UNION ALL')(self, rhs)