Django:使用values()和get_FOO_display()?

Nat*_*han 9 python django django-queryset

我正在尝试改进一些现有的代码,这些代码最初耗时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
Run Code Online (Sandbox Code Playgroud)

新代码是:

for user in users.values('name'):
   data.append(user['name'])  # Appends 'JSmith001', which is incorrect
return data
Run Code Online (Sandbox Code Playgroud)

此外,如果有其他方法来保留模型对象的创建,但只需要在后端有一个SQL语句,我很想知道它.谢谢!

nra*_*itz 6

通常,使用基于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')
Run Code Online (Sandbox Code Playgroud)