Django:使用values()和get_FOO_display()吗?
问题内容:
我正在尝试改进一些现有的代码,这些代码本来需要3分钟来准备一个大的dataTable(然后由Ajax返回)。旧代码在大型querySet上进行迭代,从各种相关对象中收集信息。从我所阅读的内容以及监视SQL日志的角度来看,遍历查询集通常是一个坏主意,因为SQL是针对每一项执行的。相反,我一直在使用值在单个SQL语句中收集信息,然后对其进行迭代。使用这种技术,我将执行时间减少到15秒以下(但我仍然没有完成)。但是,由于我不再使用模型对象,因此无法使用get_FOO_display()。有没有一种方法可以在使用values()时使用此功能?
简化后,原来是:
for user in users:
data.append(user.get_name_display()) # Appends 'Joe Smith'
return data
新的代码是:
for user in users.values('name'):
data.append(user['name']) # Appends 'JSmith001', which is incorrect
return data
另外,如果还有其他方法可以保留模型对象的创建,但在后端只需要一条SQL语句,我很想知道这一点。谢谢!
问题答案:
通常,使用基于Manager的查询返回模型对象可能会更好,更容易。听起来您原始方法的问题不在于您要遍历查询集(如@ahmoo所说,这不是性能问题),而是在迭代循环中您正在获取其他相关对象,需要一个或多个对象每个记录的其他查询。
有几种方法可以提高仍返回模型实例的查询的性能:
-
听起来最相关的是
select_related()
,它将有效地对初始查询进行表联接,以包含与外键相关的所有对象的数据。 -
如果这还不够,您还可以使用来将数据添加到模型实例中
extra()
,从而可以将子查询粘贴到SQL中。 -
如果所有操作失败,您可以使用Manager实例上的方法执行原始SQL查询
.raw()
,该实例仍将返回模型实例。
基本上,如果您可以在SQL中以每个实例只给您一行的方式进行操作,则有一种方法可以在Django中进行操作并返回模型实例。
不过,要回答您的原始问题,您可以通过Field类获取显示名称-这很丑陋:
def get_field_display(klass, field, value):
f = klass._meta.get_field(field)
return dict(f.flatchoices).get(value, value)
# usage
get_field_display(User, 'name', 'JSmith001')