高效的ModelChoiceField初始数据

0 投票
2 回答
1119 浏览
提问于 2025-04-16 14:48

为了给我的 ModelChoiceFields 设置初始数据,我现在是这样做的:

foo = ModelChoiceField(label="Foo label",
                       queryset=Foo.objects.all(),
                       initial=Foo.objects.get(pk=14))

但是我觉得这样可能不是个好习惯,而且我不太确定设置初始数据的最有效方法是什么。pk=14 是一个默认的“无效”记录。

目前,我的理解是,Foo.objects.all()Foo.objects.get(pk=14) 都是在对数据库进行单独的查询,这样会不会导致交易成本高或者是多余的查询呢?虽然 Foo 的数据库相对较小,但我还是想知道如何优化 ModelChoiceField 的定义。

2 个回答

2

你在做两个查询,但它们的执行时间完全不同。

查询集是懒惰的。Foo.objects.all() 这个查询不会在表单真正显示出来之前执行。这意味着你得到的 Foo 对象列表总是最新的。

Foo.objects.get(pk=14) 这个查询是在表单定义的时候执行的,也就是第一次导入它的模块时。所以只要服务器进程还在,这个值就会一直存在。这是好事,因为每次都不需要重新查询,但也可能有坏处,因为即使对象后来从数据库中删除了,这个值仍然会保留。

所以,针对你的具体问题,其实每次你只做了一个查询。

1

是的,你的代码确实进行了两次查询,但整体上看起来很清晰,容易理解。除非你已经分析过代码,发现这一行是个问题,否则你的代码没什么问题。

如果你真的想避免两次查询,我建议你可以看看 Django 的缓存,把查询结果缓存起来,这样在后续的页面访问中就可以避免重复查询。

initial = cache.get("foo_modelchoice_initial")
if initial is None:
    initial = Foo.objects.get(pk=14)
    cache.set("foo_modelchoice_initial", initial)

foo = ModelChoiceField(label="Foo label",
                   queryset=Foo.objects.all(),
                   initial=initial)

如果 Foo.objects.all() 的数据量变得非常大,那么这段代码可能会变得很慢。在这种情况下,你需要考虑用 AJAX 来查找数据。

撰写回答