检查元素是否存在

0 投票
3 回答
1209 浏览
提问于 2025-04-15 13:15

我想知道在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)

那么你可以在一个列表中查找另一个列表的成员,或者把一个或两个列表转换成集合来找出共同的成员等等。

撰写回答