我在索引视图中有以下代码.
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()
如果初始查询返回了十行(限制),那么保存问题10是否会更新对数据库的更新调用,或者Django是否"足够聪明"以仅发出一次更新调用?
是否有更有效的方法来实现这一结果?
您可以使用F()
对象.
以下是您导入的方式F
:from django.db.models import F
Django 1.1中的新功能.
调用更新还可以使用F()对象根据模型中另一个字段的值更新一个字段.这对于基于其当前值递增计数器特别有用.
Entry.objects.filter(is_published=True).update(views=F('views')+1)
虽然你无法对切片查询集进行更新... 编辑:实际上你可以......
这可以在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'
由于django懒惰地执行查询的方式,这导致只有2个数据库命中,无论更新了多少项.
您可以在单个事务中处理更新,这可以显着提高性能.使用单独的函数,用@ 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()