1

我有并且object其中QuerySet包含这个对象。我需要得到下一个 object一个QuerySet

我怎样才能做到这一点?

我可以通过这种方式获得下一个:

next = False
for o in QuerySet:
    if next:
        return o
    if o==object:
       next = True

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

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

4

4 回答 4

1

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

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

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

第一种解决方案:

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]

第二种解决方案:

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:
于 2020-12-20T14:41:09.910 回答
1

使用Django QuerySet API您可以尝试以下操作:

下一步:

qs.filter(pk__gt=obj.pk).order_by('pk').first()

对于以前的:

qs.filter(pk__lt=obj.pk).order_by('-pk').first()

于 2018-08-23T15:40:38.333 回答
0

Probably that is what you need (in Python 3, if you need a solution for Python 2.7, let me know):

def get_next(queryset, obj):
    it = iter(queryset)
    while obj is not next(it):
        pass
    try:
        return next(it)
    except StopIteraction:
        return None

def get_prev(queryset, obj):
    prev = None
    for o in queryset:
        if o is obj:
            break
        prev = obj
    return prev

But there are some notes:

  1. As far as full queryset is stored into the variable, you can keep an index of your object and extract next and previous ones as [i + 1] and [i - 1]. Otherwise you have to go through whole queryset to find your object there.
  2. According to PEP8 you shouldn't name variables like QuerySet, such names should be used for classes. Name it queryset.
于 2018-08-23T15:49:13.873 回答
0

也许你可以使用类似的东西:

def get_prev_next(obj, qset):
    assert obj in qset
    qset = list(qset)
    obj_index = qset.index(obj)
    try:
        previous = qset[obj_index-1]
    except IndexError:
        previous = None    
    try:
        next = qset[obj_index+1]
    except IndexError:
        next = None
    return previous,next

它不是很漂亮,但它应该工作......

于 2018-08-23T15:55:11.313 回答