Ty.*_*Ty. 22 python database django performance
我在索引视图中有以下代码.
latest_entry_list = Entry.objects.filter(is_published=True).order_by('-date_published')[:10]
for entry in latest_entry_list:
entry.views = entry.views + 1
entry.save()
Run Code Online (Sandbox Code Playgroud)
如果初始查询返回了十行(限制),那么保存问题10是否会更新对数据库的更新调用,或者Django是否"足够聪明"以仅发出一次更新调用?
是否有更有效的方法来实现这一结果?
Tom*_*ner 56
您可以使用F()对象.
以下是您导入的方式F:from django.db.models import F
Django 1.1中的新功能.
调用更新还可以使用F()对象根据模型中另一个字段的值更新一个字段.这对于基于其当前值递增计数器特别有用.
Entry.objects.filter(is_published=True).update(views=F('views')+1)
Run Code Online (Sandbox Code Playgroud)
虽然你无法对切片查询集进行更新... 编辑:实际上你可以......
这可以在django ORM中完全完成.您需要两个SQL查询:
获取非切片查询集是很难的.我想知道使用in_bulk但返回字典,而不是查询集.人们通常会使用Q objects复杂的OR类型查询,这样可以工作,但pk__in工作更简单.
latest_entry_ids = Entry.objects.filter(is_published=True)\
.order_by('-date_published')
.values_list('id', flat=True)[:10]
non_sliced_query_set = Entry.objects.filter(pk__in=latest_entry_ids)
n = non_sliced_query_set.update(views=F('views')+1)
print n or 0, 'items updated'
Run Code Online (Sandbox Code Playgroud)
由于django懒惰地执行查询的方式,这导致只有2个数据库命中,无论更新了多少项.
Jef*_*uer 13
您可以在单个事务中处理更新,这可以显着提高性能.使用单独的函数,用@ transaction.commit_manually装饰.
@transaction.commit_manually
def update_latest_entries(latest_entry_list):
for entry in latest_entry_list:
entry.views += 1
entry.save()
transaction.commit()
Run Code Online (Sandbox Code Playgroud)