-
-
Notifications
You must be signed in to change notification settings - Fork 395
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
关于 Fastapi 使用 TORTOISE_ORM 筛选查询数据时 查询出数据为空的情况 #1698
Comments
为什么同样的账号密码,第一次能查询出结果,第二次就为None |
这个跟框架没啥关系吧。tortoise orm你用的哪个版本,我现在用的0.21.5。数据库我是mysql,目前我也有分页查询和指定字段查询,一切都很正常的。 你的排查方式有哪些?目前我的项目就在用,完全没法复现。 |
我登录就一个查询用户名是否存在,再进行密码校验。但是通过我并发测试,发现,同样的用户名密码,会出现密码错误的情况,我检查了代码,没有问题。通过打印发现filter筛选出的数据,第一次有,第二次没有。 现在换了sqlalchemy一切正常,主要是我喜欢这个框架的语法,之前都是用的Django,所以写起来很舒服。我和你一样,用的0.21.5 也试过降级到 0.21.4 我怀疑起其他影响了我的这个代码。这是我使用 tortiis orm 写的登录 @users.post("/auth/login", summary='登录', description='登录')
async def login(us: LoginUserInV2):
# 查询用户信息
un = await UserInfo.filter(username=us.username).first()
if not un:
# 用户名错误
return JSONResponse(status_code=401, content={"code": 401, "data": None, "msg": '账号或密码错误'})
# 验证密码
if not verify_password(us.password, un.password):
# 密码错误
return JSONResponse(status_code=401, content={"code": 200, "data": None, "msg": '账号或密码错误'})
# 生成访问和刷新令牌
access_token_info = create_access_token(data={"username": us.username})
refresh_token_info = create_refresh_token(data={"username": us.username})
# 返回成功响应
resp = {
"code": 200,
"data": {
"token": access_token_info["access_token"],
"refreshToken": refresh_token_info["refresh_token"],
},
"msg": "登录成功"
}
return JSONResponse(status_code=200, content=resp) 这是我使用sqlalchemy写的登录 @users.post('/auth/login', summary='登录', description='登录')
async def login(us: LoginUserInV2):
async with AsyncSessionLocal() as session:
async with session.begin():
query = select(UserInfo).filter_by(username=us.username)
result = await session.execute(query)
un = result.scalars().first()
if not un:
# 用户名错误
return JSONResponse(status_code=401, content={'code': 401, 'data': None, 'msg': '账号或密码错误'})
# 验证密码
if not verify_password(us.password, un.password):
# 密码错误
return JSONResponse(status_code=401, content={'code': 401, 'data': None, 'msg': '账号或密码错误'})
# 生成访问和刷新令牌
access_token_info = create_access_token(data={'username': us.username})
refresh_token_info = create_refresh_token(data={'username': us.username})
# 返回成功响应
resp = {
'code': 200,
'data': {
'token': access_token_info['access_token'],
'refreshToken': refresh_token_info['refresh_token'],
},
'msg': '登录成功'
}
return JSONResponse(status_code=200, content=resp) |
我这边自己写了别的用ab只能简单并发测试,但是没有复现,我也用的mysql,只不过表单比较简单,请求代码逻辑也简单: 我的简易demo类似这种: def verify_group(in_name: str, db_name: str):
return in_name == db_name
n = 0
@app.get("/groups/{id}")
async def group_detail(id: int):
obj = await Group.filter(id=id).first()
global n
n += 1
if obj:
if not verify_group("Sherri Bender", obj.name):
print(obj.name, "----------", n)
return JSONResponse(
status_code=401,
content={"code": 200, "data": None, "msg": "name验证错误"},
)
return JSONResponse(
status_code=200,
content={
"code": 200,
"data": dict(obj),
"msg": "登录成功",
},
)
else:
print("not found", n) 我的压测命令: ab -n 1000 -c 200 http://127.0.0.1:8000/groups/1 压测结果: This is ApacheBench, Version 2.3 <$Revision: 1903618 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/
Benchmarking 127.0.0.1 (be patient)
Completed 100 requests
Completed 200 requests
Completed 300 requests
Completed 400 requests
Completed 500 requests
Completed 600 requests
Completed 700 requests
Completed 800 requests
Completed 900 requests
Completed 1000 requests
Finished 1000 requests
Server Software: uvicorn
Server Hostname: 127.0.0.1
Server Port: 8000
Document Path: /groups/1
Document Length: 72 bytes
Concurrency Level: 200
Time taken for tests: 1.531 seconds
Complete requests: 1000
Failed requests: 0
Total transferred: 216000 bytes
HTML transferred: 72000 bytes
Requests per second: 653.32 [#/sec] (mean)
Time per request: 306.130 [ms] (mean)
Time per request: 1.531 [ms] (mean, across all concurrent requests)
Transfer rate: 137.81 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 2 4.1 0 16
Processing: 16 284 360.0 124 1503
Waiting: 9 282 360.2 123 1503
Total: 17 286 361.0 140 1514
Percentage of the requests served within a certain time (ms)
50% 140
66% 287
75% 376
80% 540
90% 884
95% 1115
98% 1307
99% 1402
100% 1514 (longest request) print日志没有触发设置的那些错误的地方。所以,方便提供一下你的相关校验password等代码和并发测验指令么?【完整测验代码】 |
fastapi==0.111.0 这个版本在服务器环境下,查询会出现空,我升级为0.115.0版本后就没有这个问题吧 |
版本:0.21.5
API部分代码
@users.post('/auth/login', summary='登录', description='登录')
async def login(user: LoginUserInV2):
# 查询用户信息
un = await UserInfo.filter(username=user.username).first()
print(un)
print(user.username, user.password)
打印结果:
《UserInfo》
admins 32135423
INFO: 127.0.0.1:65312 - "POST /api/user/auth/login HTTP/1.1" 200 OK
INFO: 127.0.0.1:65316 - "GET /api/user/auth/getUserInfo HTTP/1.1" 401 Unauthorized
None
admins 32135423
INFO: 127.0.0.1:65319 - "POST /api/user/auth/login HTTP/1.1" 200 OK
模型:
class UserInfo(Model):
id = fields.UUIDField(
primary_key=True,
default=uuid.uuid4,
editable=False)
create_time = fields.DatetimeField(auto_now_add=True, null=True, description='创建时间')
update_time = fields.DatetimeField(auto_now=True, null=True, description='更新时间')
username = fields.CharField(max_length=256, unique=True, description='用户名')
password = fields.CharField(max_length=256, description='密码')
配置信息:
TORTOISE_ORM = {
'connections': {
'default': {
# 'engine': 'tortoise.backends.asyncpg', PostgreSQL
'engine': 'tortoise.backends.mysql', # MySQL or Mariadb
'credentials': {
'host': '127.0.0.1',
'port': '3306',
'user': 'root',
'password': '123456',
'database': 'fastapidb',
'minsize': 1,
'maxsize': 5,
'charset': 'utf8mb4',
"echo": True
}
},
},
'apps': {
'models': {
'models': ['apps.models', "aerich.models"],
'default_connection': 'default',
}
},
'use_tz': False,
'timezone': 'Asia/Shanghai'
}
The text was updated successfully, but these errors were encountered: