当前位置: 首页 > 工具软件 > pytest-flask > 使用案例 >

flask+sqlachemy+postgres+pytest

程谦
2023-12-01

记录flask+sqlachemy+postgres+pytest项目过程中的报错和解决方案

1. sqlalchemy CRUD语法

注意:修改数据库 一定要跟着session.commit()

往表中增加数据

create table(往数据库增加表信息)

new_player = pt(player_name = 'player1',sex='male')
session.add(new_player)
session.commit()

基础查询操作

query(表名)
query(表名.列名) <=> select 列名 from 表名

  1. 方法一:query+one
---返回的是对象
item_class = session.query(treasure).filter(treasure.ts_name=='maybe').one()
item_class.ts_class  --用.去访问字段
--output
'tool      '
  1. 方法二:query+first
---则返回的可以说是一个list?一个tuple一样的东西
item_class = session.query(treasure.ts_class).filter(treasure.ts_name=='maybe').first()
item_class[0] --和list/tuple取值的方法一样,下标取值
--output
'tool      '

同时 query+first也可以用于判断是否存在所要查询的值,若不存在返回None。(query+count也可以实现判断是否存在所要查询的值的判断,若不存在则返回0)

  1. 方法三: query+first()[]
--也就是将方法二直接合并了,这样的话item_class就直接去到了字符串
--返回字符串
item_class = session.query(treasure.ts_class).filter(treasure.ts_name=='maybe').first()[0]
--output
'tool      '

4.方法四:query+all()

--查询一个玩家的所有treasure
--返回list
ts_list = session.query(pt.ts_name).filter(pt.player_name==player_name).all()

更新

query(表名)

query(表名.列名) <=> select 列名 from 表名

--将player表中特定的玩家的find_or_not改为false
session.query(player)
			.filter(player.player_name == player_name)
			.update({'sex': 'male'})
--多值一起修改
session.query(player)
			.filter(player.player_name == 'player1')
			.update({'player_money':10,'login_at':time.time()})
			
session.commit() --只有了commit()了数据库才真正修改

(我现在有点怀疑.filter(player.player_name)可以用.filter('player_name')代替)
和sql有少许不同,在sql中对于单表的查询

select player_name from player where player_name = 'player1';

没有任何歧义,但是在sqlalchemy中,则可能会发生意想不到的错误(这是我找了4个小时的bug),所以在查询语句中一定要明确查询的表名,尽管只是单表查询filter(player.player_name==‘player1’)

连接join

--返回list
a=session.query(pt.ts_name)
					.join(treasure)
					.filter(treasure.ts_class=='luck',pt.player_name=='player1').all()

删除

---删除pt表中ts_name是drop_ts_name的这一行数据
session.query(pt).filter(pt.ts_name==drop_ts_name,player_name==player_name).delete()

2. postgres报错及解决方法

  • 删除不了数据库
drop database game;
#output
ERROR:  database "game" is being accessed by other users
DETAIL:  There is 1 other session using the database.

解决方法:

# 先执行:
select pg_terminate_backend(pid) from pg_stat_activity where DATNAME = 'game';
#output
 pg_terminate_backend 
----------------------
 t
(1 row)

# 再执行
drop database game;
  • 报错:
(Background on this error at: http://sqlalche.me/e/f405)

看博客有两个原因:

  1. 密码输入错误了 ,但那种情况下详细的报错应该是:
sqlalchemy.exc.ProgrammingError: (mysql.connector.errors.ProgrammingError) 1045 (28000): Access denied for user 'root'@'localhost' (using password: YES) (Background on this error at: http://sqlalche.me/e/f405)

则需要重新设置密码:(可参考)https://blog.csdn.net/tao01230/article/details/46410525

  1. 我的问题是在于数据类型不匹配

sql的schema中写的是on_sale_or_not是smallint类型,后来在py文件里,写的class

class treasure(Base): 
    __tablename__ = 'treasure'
    ts_name = Column(String(20),primary_key=True)
    on_sale_or_not = Column(Boolean)
    own_or_not = Column(Boolean) 
    wear_or_not = Column(Boolean)

中on_sale_or_not之类的写的类型为boolean所以导致了,数据类型不匹配而出现的错误

  • 报错:

date boolean这种数据类型找不到,要从

from sqlalchemy import Column,String,Integer,Boolean,Time,ForeignKey,create_engine,PrimaryKeyConstraint

import 数据类型

  • 报错
sqlalchemy.exc.InvalidRequestError: SQL expression, column, or mapped entity expected - got '<__main__.player object at 0x10b4be7f0>

在执行如下语句时:

session.query(player).filter(player.player_name=='cyy').one()

解决方案:重新建player表(因为真的疯了 对于另外的表就可以访问,这个就弄死不行,我就重新建表了,没想到还好使)

3. pytest 覆盖率运行报错

(这也是折磨我疯了的一个问题)

问题描述:pytest运行通过,但在运行coverage 的过程中,出现报错说找不到psycopg2模块

####解决方法:
查询博客/文档发现

  1. 若,pytest运行报错No module named ‘xxx’可能是pytest的路径和python路径不一致的原因
  • 可以用which查看一下pytest和python的路径,若不一致,则可以在当前路径下重新安装pytest即可
  1. 若,pytest运行通过,但使用coverage run -m pytest生成覆盖率时报错,No module named ‘ psycopg2’。
  • 解决方法:用pytest的pytest-cov插件即可
    安装:pip install pytest-cov
    运行:py.test --cov=myproj tests/

post和get的区别

  • GET在浏览器回退时是无害的,而POST会再次提交请求。
  • GET产生的URL地址可以被Bookmark,而POST不可以。
  • GET请求会被浏览器主动cache,而POST不会,除非手动设置。
  • GET请求只能进行url编码,而POST支持多种编码方式。
  • GET请求参数会被完整保留在浏览器历史记录里,而POST中的参数不会被保留。
  • GET请求在URL中传送的参数是有长度限制的,而POST么有。对参数的数据类型,GET只接受ASCII字符,而POST没有限制。
  • GET比POST更不安全,因为参数直接暴露在URL上,所以不能用来传递敏感信息。
  • GET参数通过URL传递,POST放在Request body中。

参考链接

post/get参考链接:https://www.cnblogs.com/logsharing/p/8448446.html
pytest-cov参考链接:https://pypi.org/project/pytest-cov/2.0.0/

 类似资料: