按对象从 QuerySet 获取下一个和上一个对象

Mil*_*ano 2 python django django-orm django-queryset django-2.1

我有 and objectQuerySet其中包含这个对象。我需要获取下一个 object一个QuerySet

我怎样才能做到这一点?

我可以这样进行下一步:

next = False
for o in QuerySet:
    if next:
        return o
    if o==object:
       next = True
Run Code Online (Sandbox Code Playgroud)

但我认为在巨大的QuerySets 上这是非常缓慢且低效的方法。

您知道更好的解决方案吗?

Dol*_*arl 5

我知道这个问题有点老了,但我遇到过这个问题,但没有找到非常有效的解决方案,所以我希望它可以对某人有所帮助。我想出了两个非常好的解决方案。

第一个更优雅,但性能稍差。第二个明显更快,特别是对于较大的查询集,但它结合使用原始 SQL。

它们都找到上一个和下一个ids,但当然可以进行调整以检索实际的对象实例。

第一个解决方案:

object_ids = list(filtered_objects.values_list('id', flat=True))
current_pos = object_ids.index(my_object.id)
if current_pos < len(object_ids) - 1:
    next_id = object_ids[current_pos + 1]
if current_pos > 0:
    previous_id = object_ids[current_pos - 1]
Run Code Online (Sandbox Code Playgroud)

第二个解决方案:

window = {'order_by': ordering_fields}
with_neighbor_objects = filtered_objects.annotate(
    next_id=Window(
        Lead('id'),
        **window
    ),
    previous_id=Window(
        Lag('id'),
        **window
    ),
)
sql, params = with_neighbor_objects.query.sql_with_params()
#  wrap the windowed query with another query using raw SQL, as
#  simply using .filter() will destroy the window, as the query itself will change.
current_object_with_neighbors = next(r for r in filtered_objects.raw(f"""
        SELECT id, previous_id, next_id FROM ({sql}) filtered_objects_table
        WHERE id=%s
    """, [*params, object_id]))

next_id = current_object_with_neighbors.next_id:
previous_id = current_object_with_neighbors.previous_id:
Run Code Online (Sandbox Code Playgroud)