Get the index of an element in a queryset

后端 未结 6 809
佛祖请我去吃肉
佛祖请我去吃肉 2020-12-04 18:08

I have a QuerySet, let\'s call it qs, which is ordered by some attribute which is irrelevant to this problem. Then I have an object, let\'s call it obj

相关标签:
6条回答
  • 2020-12-04 18:15

    If you just want to know where you object sits amongst all others (e.g. when determining rank), you can do it quickly by counting the objects before you:

        index = MyModel.objects.filter(sortField__lt = myObject.sortField).count()
    
    0 讨论(0)
  • 2020-12-04 18:23

    Assuming for the purpose of illustration that your models are standard with a primary key id, then evaluating

    list(qs.values_list('id', flat=True)).index(obj.id)
    

    will find the index of obj in qs. While the use of list evaluates the queryset, it evaluates not the original queryset but a derived queryset. This evaluation runs a SQL query to get the id fields only, not wasting time fetching other fields.

    0 讨论(0)
  • 2020-12-04 18:26

    QuerySets in Django are actually generators, not lists (for further details, see Django documentation on QuerySets).
    As such, there is no shortcut to get the index of an element, and I think a plain iteration is the best way to do it.

    For starter, I would implement your requirement in the simplest way possible (like iterating); if you really have performance issues, then I would use some different approach, like building a queryset with a smaller amount of fields, or whatever.
    In any case, the idea is to leave such tricks as late as possible, when you definitely knows you need them.
    Update: You may want to use directly some SQL statement to get the rownumber (something lie . However, Django's ORM does not support this natively and you have to use a raw SQL query (see documentation). I think this could be the best option, but again - only if you really see a real performance issue.

    0 讨论(0)
  • 2020-12-04 18:27

    Compact and probably the most efficient:

    for index, item in enumerate(your_queryset):
        ...
    
    0 讨论(0)
  • 2020-12-04 18:31

    It's possible for a simple pythonic way to query the index of an element in a queryset:

    (*qs,).index(instance)
    

    This answer will unpack the queryset into a list, then use the inbuilt Python index function to determine it's position.

    0 讨论(0)
  • 2020-12-04 18:40

    You can do this using queryset.extra(…) and some raw SQL like so:

    queryset = queryset.order_by("id")
    record500 = queryset[500]
    
    numbered_qs = queryset.extra(select={
        'queryset_row_number': 'ROW_NUMBER() OVER (ORDER BY "id")'
    })
    
    from django.db import connection
    cursor = connection.cursor()
    cursor.execute(
        "WITH OrderedQueryset AS (" + str(numbered_qs.query) + ") "
        "SELECT queryset_row_number FROM OrderedQueryset WHERE id = %s",
        [record500.id]
        )
    index = cursor.fetchall()[0][0]
    
    index == 501 # because row_number() is 1 indexed not 0 indexed
    
    0 讨论(0)
提交回复
热议问题