Django数据库双条件过滤返回空QuerySet,排查过滤逻辑正确性
我帮你梳理下代码里可能导致这个问题的几个关键点,咱们一步步来:
1. dateUsed字段的auto_now=True会覆盖手动赋值
你的Song模型里dateUsed设置了auto_now=True,这个参数的作用是每次调用save()时,自动将字段更新为当前日期/时间。这意味着你在reload()函数里手动设置的currentSong.dateUsed = datetime.now().date() - timedelta(days=1)会被Django忽略,最终dateUsed还是会被改成当前日期。
如果你的测试逻辑依赖于手动设置的过去日期,这会导致筛选逻辑看起来“失效”——因为实际存储的dateUsed是当前日期,本应该被包含,但如果还有其他问题的话就会返回空。
解决办法:如果需要手动控制dateUsed的赋值,把auto_now=True改成手动管理字段值:
dateUsed = models.DateField() # 去掉auto_now=True,后续手动设置值
2. reload()函数中的模型名错误与查询语法问题
你在reload()里写的是currentSong = Songs.objects.get(entry["songEnt"].name),但你的模型类是Song(单数),不是Songs(复数)。而且get()方法需要明确指定字段(比如title=xxx),直接传字符串会抛出FieldError。
这意味着这段代码可能根本没有正确执行,导致没有任何Song对象被设置为used=True,自然筛选结果为空。修正后的代码应该是:
def reload(): # Change status of old song/album to used, and save the date that it was used if entry["status"] == "filled": # 修正模型名为Song,并且明确查询字段 currentSong = Song.objects.get(title=entry["songEnt"].name) currentAlbum = Albums.objects.get(name=entry["albumEnt"].name) # 假设Album模型有name字段 currentSong.dateUsed = datetime.now().date() - timedelta(days=1) currentAlbum.dateUsed = datetime.now().date() - timedelta(days=1) currentSong.used = True currentAlbum.used = True currentSong.save() currentAlbum.save()
3. 筛选条件的边界问题(可选)
你的筛选条件是dateUsed__gt = window,window是当前日期减20天。这意味着只会包含dateUsed严格大于window的记录,比如window是10月1日,那10月1日当天的记录不会被包含。如果你想包含window当天的记录,应该用dateUsed__gte = window:
songHistory = Song.objects.filter(used=True).filter(dateUsed__gte=window)
快速验证步骤
建议你先做以下几步确认问题:
- 直接在Django shell里查询数据库,确认是否存在符合条件的记录:
# 在终端执行python manage.py shell后输入 from datetime import datetime, timedelta from your_app.models import Song window = datetime.now().date() - timedelta(days=20) print(Song.objects.filter(used=True, dateUsed__gte=window)) - 检查
reload()函数是否被正确调用,有没有抛出异常。可以在函数里加print语句或者日志来调试执行情况。
内容的提问来源于stack exchange,提问作者Utheri Wagura

