简体   繁体   中英

Slicing QuerySet with [n:] and [n: end] gives different results when using .values_list()

In pure python, [n:] and [n: len(mylist)] are equivalent. However it is not true with Django QuerySet .

I ran into this issue:

# ci is a QuerySet
In [88]: id_name_value = list(ci[ci.count() - 1000:].values_list("id", "attributes__name", "attributes__value"))

In [89]: len(id_name_value)
Out[89]: 7254

In [90]: id_name_value = list(ci[ci.count() - 1000 : ci.count()].values_list("id", "attributes__name", "attributes__value"))

In [91]: len(id_name_value)
Out[91]: 1000

Where the behaviour is clearly not the same. In this case [n: QuerySet.count()] gives me what I want, and [n:] does something else, but what does it do?

Edit:

The items that I get from:

In [4]: temp = ci[ci.count()-1000:]

# and 

In [6]: temp_2 = ci[ci.count()-1000: ci.count()]

are the same, the difference shows up when I apply .values_list()

The issue here is that you are fetching values from a related model attributes.

values_list("id", "attributes__name", "attributes__value")

That means that ids will be duplicated in the results. Each id will appear once for each related attribute.

You therefore get lists of two different lengths, because ci.count() (the number of unique ids) is not the same as the length of the values queryset (which has duplicates).

To get the last 1000 values of the values queryset, you could do:

ci[ci.values_list("id", "attributes_name", "attributes_value").count() - 1000:].values_list("id", "attributes__name", "attributes__value"))

or

ci.reverse()[:1000].values_list("id", "attributes__name", "attributes__value")

Note that the second queryset will have the items in reverse order.

If you do qs[n:] then it'll give you the last n objects, and the reverse [:n] gives you the first n objects.

Furthermore, if you do qs[o:l] then o is an offset and l is a limit.

For example qs = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

first = qs[:3]
# first == [0, 1, 2]

last = qs[3:]
# last == [7, 8, 9]

offset = qs[2:6]
# offset = [3, 4, 5]

These can be found in the docs for limiting a queryset.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM