结果查询

上节课使用query从数据库中查询到了结果,但是query返回的对象是直接可用的吗?

首先导入模块

from connect import session
from user_modules import User

query返回对象

rs = session.query(User)
print(rs)
for i in rs:
print(i)
#---------------------------------- #根据返回结果来看, rs 是一个 Query 对象,打印出来可以看到转化的 SQL

rs = session.query(User).filter(User.username'塔卡')



#all 是返回所有符合条件的数据

rs = session.query(User).all() #查询所有数据,返回一个列表

print(rs)

print(rs[0].username) #属性访问



#first 是返回所有符合条件数据的第一条数据

rs = session.query(User).first() #查询第一条数据



#[0] 和 first 类似,但是如果没有符合条件的数据则会报错

session.query(User).filter(User.username'budong')[0]



#这里,在 query 中查询对象的某个属性值 ( 对应为查询表中某个字段的值 ),返回的结果不再是一个 Query 对象,而是一个列表

rs = session.query(User.username).filter(User.username == '塔卡').all()



#同理,但是 first 返回结果是一个元组

rs = session.query(User.username).filter(User.username == '塔卡').first()



#[0] 和 first 类似,但是如果没有符合条件的数据则会报错

session.query(User.username).filter(User.username=='budong')[0] #getattr(rs[0], 'username'), rs[0].username这两种方式可以取到具体的数据值

rs = session.query(User).filter(User.username=='budong').all()

print(hasattr(rs,'username'))

print(getattr(rs,'username','litao')) rs = session.query(User)[0:2] #索引取值

print(rs)

# rs2 = session.query(User).filter(User.username=='塔卡').all()

print(rs,type(rs))

条件查询一

过滤函数

filter 是一个过滤函数,过滤条件都可以书写在此函数中,不同的条件之间用 逗号 分隔

filter_by 也是一个过滤函数,但是功能要弱一些

filter 和 filter_by 的区别

二者都是 过滤函数,但是使用有如下差别:

1. filter 中需要添加 类对象,filter_by不需要

2. filter_by 中只能添加等于的条件,不能添加 不等于、大于小于等条件,filter没有这个限制

rs = session.query(User.username).filter(User.username == '塔卡')
rs2 = session.query(User.username).filter_by(username = '塔卡')
print(rs)

like 和 notlike

like 是模糊查询,和数据库中的 like 用法一样

notlike 和 like 作用相反

rs = session.query(User).filter(User.username.like('%塔%')).all()
rs = session.query(User).filter(User.username.notlike('%塔%')).all()

in_  和 notin_

in_ 和 notin_ 是范围查找,参数为列表

rs = session.query(User.username).filter(User.username.in_(['塔卡','小泼'])).all()
rs = session.query(User.username).filter(User.username.notin_(['塔卡','小泼'])).all()

is_ 和 isnot

is_  和 isnot  精确查找

rs = session.query(User).filter(User.username.is_(None)).all()
rs = session.query(User).filter(User.username.isnot(None)).all()
#判断为空还可以使用:
session.query(User.id).filter(User.username==None).all()

查询结果数:限制查询

all、limit、offset、slice、one

rs  =session.query(User.username).all()
print(rs)
rs =session.query(User.username).limit(2).all() #限制数量查询
rs =session.query(User.username).offset(2).all() #偏移量
rs =session.query(User.username).slice(1,4).all() #切片 #不管怎样写one只能查一条数据,如果有多条重复数据,会报错

sqlalchemy.orm.exc.MultipleResultsFound: Multiple rows were found for one()

rs = session.query(User.username).filter(User.username == '李涛').one()

print(rs)

排序:倒叙先进行导入desc

from sqlalchemy import desc
rs = session.query(User.username,User.id).order_by(User.id).all() #升序排列
rs = session.query(User.username,User.id).order_by(desc(User.id)).all() #综合使用

rs = session.query(User.username,User.id).order_by(desc(User.id)).filter(User.username == '李涛').all()

print(rs)

聚合函数

func.count

使用函数时,需要导入 func, group_by 和 order_by 一样,是可以直接使用的,不需要导入

having 也可以直接使用,使用方法也和 SQL 中使用类似

func.sum、func.max、func.min

extract

extract 提取对象中的数据,这里提取分钟,并把提取出来的结果用 label 命名别名,之后就可以使用 group_by 来分组

count 里面同样可以使用 *

or_

or_ 是或者的意思,和数据库中的 or 一样

# 分组查询与聚合函数一起使用
from sqlalchemy import func,extract,or_
# rs = session.query(User.password,func.count(User.id)).group_by(User.password).all()
# rs = session.query(User.password,func.count(User.id)).group_by(User.password).having(func.count(User.id) >1).all()
# print(rs) # rs = session.query(User.password,func.sum(User.id)).group_by(User.password).all()

rs = session.query(User.password,func.max(User.id)).group_by(User.password).all()

rs = session.query(User.password,func.min(User.id)).group_by(User.password).all()

print(rs)

#extract

rs = session.query(extract('minute',User.create_time).label('minute'),func.count(User.id)).group_by('minute').all()

#or_

rs = session.query(User.username).filter(or_(User.username.isnot(None),User.password == '')).all()

print(rs)

 3 多表查询

在user_modules.py中增加一张表UserDetails表

class UserDetails(Base):
__tablename__='user_details'
id = Column(Integer, primary_key=True, autoincrement=True)
id_card = Column(Integer,nullable=True,unique=True)
lost_login = Column(DateTime)
login_num = Column(Integer,default=0)
user_id = Column(Integer,ForeignKey('user.id'))
</span><span style="color: #0000ff;">def</span> <span style="color: #800080;">__repr__</span><span style="color: #000000;">(self):
</span><span style="color: #0000ff;">return</span> <span style="color: #800000;">'</span><span style="color: #800000;">&lt;UserDetails(id=%s,id_card=%s,last_login=%s,login_num=%s,user_id=%s)&gt;</span><span style="color: #800000;">'</span>%<span style="color: #000000;">(
self.id,
self.id_card,
self.lost_login,
self.login_num,
self.user_id
)</span></pre>

在query_test.py文件中导入新增加的表

from user_modules import User,UserDetails

笛卡尔连接:

rs =session.query(User.username,UserDetails.lost_login).filter(UserDetails.user_id==User.id).all()

去掉.all(),查看原生SQL如下:

SELECT user.id AS user_id, user.username AS user_username, user.password AS user_password, 
user.create_time AS user_create_time, user._locked AS user__locked, user_details.id AS user_details_id,
user_details.id_card AS user_details_id_card, user_details.lost_login AS user_details_lost_login,
user_details.login_num AS user_details_login_num, user_details.user_id AS user_details_user_id
FROM user, user_details
WHERE user_details.user_id = user.id

inner join:内连接

rs = session.query(User.username,UserDetails.lost_login).\
join(UserDetails,UserDetails.user_id == User.id)

查看原生SQL如下:

SELECT user.username AS user_username, user_details.lost_login AS user_details_lost_login
FROM user INNER JOIN user_details ON user_details.user_id = user.id

###使用笛卡尔积的filter条件与使用inner join运行的结果一致。但运行的原生sql不一致。

left join:外连接,可以将两张表对调

rs = session.query(User.username,UserDetails.lost_login).\
outerjoin(UserDetails,UserDetails.user_id==User.id).all() # print(rs)

运行SQL如下:

SELECT user.username AS user_username, user_details.lost_login AS user_details_lost_login
FROM user LEFT OUTER JOIN user_details ON user_details.user_id = user.id

运行结果如下:

#两张表对调
rs = session.query(UserDetails.lost_login,User.username).\
outerjoin(User,UserDetails.user_id==User.id).all() # print(rs)

运行SQL如下:

SELECT user_details.lost_login AS user_details_lost_login, user.username AS user_username
FROM user_details LEFT OUTER JOIN user ON user_details.user_id = user.id

运行结果如下:

union:

联合查询,有自动去重的功能,对应的还有 union_all

q1 = session.query(User.id)
q2 = session.query(UserDetails.user_id)
# print(q1.union(q2).all())

子表查询

声明子表

sql_0 = session.query(UserDetails.lost_login).subquery() #声明子表
#使用
# print(session.query(User,sql_0.c.lost_login))

运行结果如下:

SELECT user.id AS user_id, user.username AS user_username, user.password AS user_password, 
user.create_time AS user_create_time, user._locked AS user__locked, anon_1.lost_login AS anon_1_lost_login
FROM user, (SELECT user_details.lost_login AS lost_login
FROM user_details) AS anon_1

原生SQL查询:

sql_1 = '''
select * from `user`
'''
#查询
row = session.execute(sql_1)
#循环取值
# for i in row:
# print(i)

#取值
print(row)
#fetch会记录游标运行了上面的for以后下面就查不到数据
print(row.fetchone()) #查询一条
print(row.fetchmany()) #在多查询一条
print(row.fetchall()) # 差剩下的所有

一对一表关系

Module

需要先创建对应的 Module ,这里采用之前建立好的 User 和 UserDetails

from sqlalchemy.orm import relationship
....
class User(Base):
.....
class UserDetails(Base):
......
userdetail </span>= relationship(<span style="color: #800000;">'</span><span style="color: #800000;">User</span><span style="color: #800000;">'</span>,backref=<span style="color: #800000;">'</span><span style="color: #800000;">details</span><span style="color: #800000;">'</span>,uselist=False,cascade=<span style="color: #800000;">'</span><span style="color: #800000;">all</span><span style="color: #800000;">'</span><span style="color: #000000;">)
</span><span style="color: #008000;">#</span><span style="color: #008000;">SQLAlchemy里面用来表示表关系的,一对一</span>
<span style="color: #008000;">#</span><span style="color: #008000;">relationship只在模型层面上生效,只在模型层面上</span>
<span style="color: #0000ff;">def</span> <span style="color: #800080;">__repr__</span><span style="color: #000000;">(self):
........</span></pre>

自动添加属性

在刚才这里, User 里面本来是没有 details 这个属性的,但是在 UserDetails 里面添加 relationship 之后, User 实例会自动加上 details 属性

relationship

表关系是逻辑上的关系,但是 mysql 中并没有直接说明表关系的东西,外键约束是一个表现形式,外键是一种表之间的约束,可以用来表示这种关系

在SQLAlchemy里面,这个relationship代表了一对多的关系,当然我们可以通过参数改变关系,它默认是一对多的关系,而这个关系是SQLAlchemy里面的,和数据库没有关系,但是relationship是和外键一起使用的。

反向查询

row = session.query(User).get(4)
print(row)
print(row.details) #会把对应的详情表里面的对应的信息打印出来

结果为:

        <User(id=4,username=小泼,password=55432,create_time=2019-04-01 23:10:56,_locked=False)>

[<UserDetails(id=2,id_card=543,last_login=2019-04-02 23:35:38,login_num=4,user_id=4)>]

正向查询:

row= session.query(UserDetails).get(2)
print(row)
print(row.userdetail)

结果为:

<UserDetails(id=2,id_card=543,last_login=2019-04-02 23:35:38,login_num=4,user_id=4)>
    &lt;User(id=4,username=小泼,password=55432,create_time=2019-04-01 23:10:56,_locked=False)&gt;</pre>

使用一对多

relationship 默认是 一对多 关系

uselist

uselist=True

默认是 True ,因此可以省略不写

多对多表关系

用户 和 文章之间,可以是一对多的关系,但是如果用户转载的话,就可以看成是 多对多 关系,那 多对多 关系在 SQLAlchemy 中怎么表示呢?

在Module中创建中间表

from sqlalchemy import Table

user_article = Table('user_article', Base.metadata,

Column('user_id', Integer, ForeignKey('user.id'), primary_key=True), #联合主键

Column('article_id', Integer, ForeignKey('article.id'), primary_key=True)

)

在Module中创建  文章Module

class Article(Base):
__tablename__ = 'article'
id = Column(Integer,primary_key=True,autoincrement=True)
content = Column(String(500),nullable=True)
create_time = Column(DateTime,default=datetime.now)
article_user </span>= relationship(<span style="color: #800000;">'</span><span style="color: #800000;">User</span><span style="color: #800000;">'</span>,backref = <span style="color: #800000;">'</span><span style="color: #800000;">article</span><span style="color: #800000;">'</span>,secondary=<span style="color: #000000;">user_article)

</span><span style="color: #0000ff;">def</span> <span style="color: #800080;">__repr__</span><span style="color: #000000;">(self):
</span><span style="color: #0000ff;">return</span> <span style="color: #800000;">'</span><span style="color: #800000;">Article(id=%s, content=%s, creat_time=%s)</span><span style="color: #800000;">'</span> %<span style="color: #000000;"> (
self.id,
self.content,
self.create_time
)</span></pre>

调用测试:

row = session.query(User).get(4)
print(dir(row))
print(row)
print(row.article)
print(row.details) #会把对应的详情表里面的对应的信息打印出来

结果展示:

['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', 

'__getattribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__mapper__', '__module__',

'__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__',
'__subclasshook__', '__table__', '__tablename__', '__weakref__', '_decl_class_registry', '_locked', '_sa_class_manager',

'_sa_instance_state', 'article', 'create_time', 'details', 'id', 'metadata', 'password', 'username']
    </span>&lt;User(id=4,username=小泼,password=55432,create_time=2019-04-01 23:10:56,_locked=False)&gt;<span style="color: #000000;">

[Article(id=1, content=litao进阶了, creat_time=2019-04-05 18:51:34), Article(id=2, content=式微走了, creat_time=2019-04-01 18:52:06)]

[<UserDetails(id=2,id_card=543,last_login=2019-04-02 23:35:38,login_num=4,user_id=4)>]

包跟包管理

当把 Module 写好之后,该如何调用呢?

在模块中直接导入:

from data.user_modules import UserDetails

执行06-login.py,报错结果如下:

Traceback (most recent call last):
File "/home/pyvip/tornado_pro/06-login.py", line 11, in <module>
from data.user_modules import UserDetails
File "/home/pyvip/tornado_pro/data/user_modules.py", line 2, in <module>
from connect import Base
ImportError: No module named 'connect'

解决方法:

简单登录

定义06-login.py 文件

import sys
import tornado.web
import tornado.ioloop
import tornado.httpserver
import tornado.options
from tornado.web import RequestHandler
from tornado.options import define,options
import util.ui_modules
import util.ui_methods
# import time
from data.connect import session
from data.user_modules import UserDetails, User define('port',default=8080,help='run server',type=int) #

class MainHandler(RequestHandler):

def get(self):

self.write('请去login') class LoginHandler(RequestHandler):

def get(self):

self.render('in_out.html')
</span><span style="color: #0000ff;">def</span><span style="color: #000000;"> post(self):
</span><span style="color: #800000;">'''</span><span style="color: #800000;">验证逻辑</span><span style="color: #800000;">'''</span><span style="color: #000000;">
user </span>= self.get_argument(<span style="color: #800000;">'</span><span style="color: #800000;">name</span><span style="color: #800000;">'</span><span style="color: #000000;">,None)
password </span>= self.get_argument(<span style="color: #800000;">'</span><span style="color: #800000;">password</span><span style="color: #800000;">'</span><span style="color: #000000;">,None)
</span><span style="color: #008000;">username = session.query(User).filter(User.username == user).first()</span><span style="color: #0000ff;">print</span><span style="color: #000000;">(username)
</span><span style="color: #0000ff;">if</span> username <span style="color: #0000ff;">and</span> password ==<span style="color: #000000;"> username.password:
self.render(</span><span style="color: #800000;">'</span><span style="color: #800000;">02-templates.html</span><span style="color: #800000;">'</span><span style="color: #000000;">,
username </span>=<span style="color: #000000;"> username.username
)
</span><span style="color: #0000ff;">else</span><span style="color: #000000;">:
self.write(</span><span style="color: #800000;">'</span><span style="color: #800000;">登录失败</span><span style="color: #800000;">'</span><span style="color: #000000;">)

application = tornado.web.Application(

handlers=[

(r'/',MainHandler),

(r'/login',LoginHandler),

],

debug=True,

template_path = 'templates',

static_path='static',

# autoescape = None, #全局取消转义

ui_methods=util.ui_methods,

ui_modules=util.ui_modules

)

if name == 'main':

tornado.options.parse_command_line()

http_server = tornado.httpserver.HTTPServer(application)

http_server.listen(options.port)

tornado.ioloop.IOLoop.current().start()

渲染模板02-templates.html为

<!DOCTYPE html>
{#去掉整个页面的转义#}
{#{% autoescape None %}#}
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Templates</title>
</head>
<body>
{% if username !='' %}
欢迎 {{ username }} 登录
<img src="static/images/01.jpg" width="200px" alt="">
<img src="{{ static_url('images/02.webp') }}" width="200px" alt="">
{% else %}
亲,请登录
{% end %}
</body>
</html>

登录成功返回如下内容:

登录失败返回:

将LoginHandler的post方法的代码简化为get_name方法:

class LoginHandler(RequestHandler):
def get(self):
self.render('in_out.html')
def post(self):
'''验证逻辑'''
user = self.get_argument('name',None)
password = self.get_argument('password',None)
# username = session.query(User).filter(User.username == user).first()
username = User.get_name(user)
print(username)
if username and password == username.password:
self.render('02-templates.html',
username = username.username
)
else:
self.write('登录失败')

在user_modules.py文件的User Module下定义get_name方法:

class User(Base):
  。。。。
def __repr__(self):
return '''
<User(id=%s,username=%s,password=%s,create_time=%s,_locked=%s)>
'''%(self.id,self.username,self.password,self.create_time,self._locked)
@classmethod
def get_name(cls,user):
'''用来查询用户名的方法'''
return session.query(cls).filter(cls.username == user).first()

最新文章

  1. SQL查询某个时间段共多少条数据
  2. PyQt 自定义信号带参数
  3. unity awake start 的区别
  4. 贪心算法 hdu 1009
  5. python 数据库 blob类型 转字符串
  6. Java 两个变量交换值
  7. ios系统下,html5拍照上传的压缩处理
  8. IntelliJ IDEA启动web项目时突然变慢的原因
  9. WIN2003+IIS6+FastCGI+PHP5.4.30的安装配置
  10. java web轻量级开发面试教程内容精粹:哪些简历得不到面试机会
  11. 下载python的Crypto库出现的问题的解决:ModuleNotFoundError: No module named &#39;Crypto&#39;
  12. Unity3D学习(六):《Unity Shader入门精要》——Unity的基础光照
  13. 关于JDBC学习过程中的注意事项(分享自己犯过的错误,写给初学JDBC的小伙伴的八条建议)
  14. zabbix监控windows服务器
  15. pthread_once详解和使用
  16. Unity Frame Debugger连接Android真机调试
  17. Vue 使用细节收集
  18. (C/C++学习笔记) 十八. 继承和多态
  19. 【转】每天一个linux命令(23):Linux 目录结构
  20. B/S与C/S的差别

热门文章

  1. 【转】理解并设计rest/restful风格接口
  2. java加密类
  3. MongoDB高级知识(六)
  4. 2019 SDN阅读作业
  5. keras.preprocessing.text.Tokenizer
  6. 小明工具箱&lt;Excel 插件&gt;&lt;VSTO 插件&gt;
  7. redis.windows.conf 配置注释
  8. Java连载1-概述&amp;常用的dos命令
  9. Kafka界面管理工具-kafkamanager
  10. linux 查找被删除但是未被释放空间的文件 并释放资源