我有object
和QuerySet
,其中包含此对象。我需要获得此object
的下一个和上一个 QuerySet
。
我该怎么做?
我可以这样下一个:
next = False
for o in QuerySet:
if next:
return o
if o==object:
next = True
但是我认为在大型QuerySet
上这是一种非常缓慢且效率低下的方法。
您知道更好的解决方案吗?
答案 0 :(得分:1)
我知道这个问题有点老了,但我遇到了这个问题并且没有找到非常有效的解决方案,所以我希望它可以帮助某人。 我想出了两个很好的解决方案。
第一个更优雅,但性能稍差。第二个明显更快,特别是对于较大的 QuerySets,但它结合使用原始 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:
答案 1 :(得分:0)
使用Django QuerySet API
,您可以尝试以下操作:
对于下一个:
qs.filter(pk__gt=obj.pk).order_by('pk').first()
对于上一个:
qs.filter(pk__lt=obj.pk).order_by('-pk').first()
答案 2 :(得分:0)
可能就是您所需要的(在Python 3中,如果您需要Python 2.7的解决方案,请告诉我):
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
但是有一些注意事项:
[i + 1]
和[i - 1]
。否则,您必须遍历整个queryset
才能在此处找到对象。QuerySet
之类的变量,此类名称应用于类。将其命名为queryset
。答案 3 :(得分: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
它不是很漂亮,但是应该可以工作...