检查元素是否存在
我想知道在Django模型中,某个元素是否存在。我觉得这应该很简单,但在Django文档的查询部分中找不到什么优雅的方法。
我遇到的问题是,我有成千上万张截图存放在一个文件夹里,需要检查这些截图是否在应该存储它们的数据库中。所以我在遍历文件名,想要查看每个文件名对应的元素是否存在。我的模型叫做Screenshot,我想到的唯一方法是
filenames = os.listdir(settings.SCREENSHOTS_ON_DISC)
for filename in filenames:
exists = Screenshot.objects.filter(filename=filename)
if exists:
...
有没有更好或更快的方法来做到这一点?请注意,一张截图在数据库中可能出现多次(所以我没有使用.get)。
3 个回答
1
这个查询可以让你获取数据库和文件系统中的所有文件:
discfiles = os.listdir(settings.SCREENSHOTS_ON_DISC)
filenames = (Screenshot.objects.filter(filename__in=discfiles)
.values_list('filename', flat=True)
.order_by('filename')
.distinct())
注意这里的 order_by
。如果你在模型定义中指定了排序,那么使用 distinct
可能不会返回你想要的结果。这个问题在这里有说明:
所以,要明确指定排序,然后再执行查询。
1
你可以试试:
Screenshot.objects.filter(filename__in = filenames)
这样做会给你一个你所有截图的列表。你可以对比这两个列表,看看哪些截图是缺失的。这应该能帮你入门,不过你可能还想调整一下查询,以提高性能或方便使用。
2
如果你的 Screenshot
模型有很多属性,那么你展示的代码其实做了一些不必要的工作,没必要这么复杂。比如,你可以这样做:
files_in_db = Screenshot.objects.values_list('filename', flat=True).distinct()
这样可以得到数据库中所有文件名的列表,并生成SQL语句只去获取这些文件名。它不会尝试去创建和填充 Screenshot 对象。如果你有
files_on_disc = os.listdir(settings.SCREENSHOTS_ON_DISC)
那么你可以在一个列表中查找另一个列表的成员,或者把一个或两个列表转换成集合来找出共同的成员等等。