0

I would like to get your help according to my issue : StopIteration.

Principe:

I have a function which get as arguments a list of ids and a specific id. This list of ids corresponds to an array with pagination.

This function is called when I create a new object in this array. Once my object is created, I'm redirected to the good page in my array.

My function:

def get_pagination(my_list_of_objects, pk):
    # if object doesn't exist, add id to list of objects
    if pk not in my_list_of_objects:
        my_list_of_objects.append(pk)

    # Get the list of objects code splitted by PAGE_LIMIT sorted by code (default)
    my_list_of_objects_code = MyModel.objects.values_list('code', flat=True).filter(id__in=my_list_of_objects)
    pagination = [my_list_of_objects_code[x:x + settings.PAGE_LIMIT] for x in range(0, len(my_list_of_objects_code), settings.PAGE_LIMIT)]

    # Get first and last page number
    first_page = 1
    last_page = len(pagination)

    # Get sublist index (e.g page number for specific id)
    page_number = (next(index for index, value in enumerate(pagination) if pk in value)) + 1
    return pagination, first_page, last_page, page_number

Through this way :

my_list_of_objects: list of objects id

my_list_of_objects_code: list of objects sorted by code

pagination: Split the list in sublists with n elements inside. n corresponds to pagination set in settings.

first_page: first page number (e.g 1 as default)

last_page: last_page number (e.g number of sublists)

page_number: get the page number where is located my object created

Example:

settings.PAGE_LIMIT = 5
pk: 119
my_list_of_objects_code: <QuerySet ['a', 'aa', 'aaa', 'aaaa', 'aasza', 'abaaa', 'aqqq', 'asz', 'asza', 'awq', 'azazaza', 'azeaze', 'bgre', 'cdezf', 'da',...]>
pagination: [['a', 'aa', 'aaa', 'aaaa', 'aasza'], ['abaaa', 'aqqq', 'asz', 'asza', 'awq'], ['azazaza', 'azeaze', 'bgre', 'cdezf', 'da']...]
first_page: 1
last_page: 18

Issue:

When I call my function, I get this issue :

Exception Type: StopIteration

File "/home/Bureau/Projets/APP/my_app/src/my_app/views/main.py" in get_pagination 1830. page_number = (next(index for index, value in enumerate(pagination) if pk in value)) + 1

I don't understand How I can pass this issue. If I need try/except what I have to do ?

Thank you

EDIT:

def get_pagination(my_list_of_objects, pk):
    # if object doesn't exist, add id to list of objects
    if pk not in my_list_of_objects:
        my_list_of_objects.append(pk)

    # Get the list of objects code splitted by PAGE_LIMIT sorted by code (default)
    my_list_of_objects_code = MyModel.objects.values_list('code', flat=True).filter(id__in=my_list_of_objects)
    pagination = [my_list_of_objects_code[x:x + settings.PAGE_LIMIT] for x in range(0, len(my_list_of_objects_code), settings.PAGE_LIMIT)]

    # Get first and last page number
    first_page = 1
    last_page = len(pagination)

    try:
        page_number = (next(index for index, value in enumerate(pagination) if MyModel.objects.get(pk=pk).code in value)) +1

    except StopIteration:
        page_number = 1
    return pagination, first_page, last_page, page_number
Essex
  • 6,042
  • 11
  • 67
  • 139
  • why are you using `next`? `StopIteration` means the iterator has exhausted the values, so there isn't any value left. E.g. when you iterate over a list of 2 elements, the third time you call `next` it will raise `StopIteration`. But in your case, calling `next` doesn't make sense, if you just want the first element (which is what you'll get since you iterator is created again for every request) – dirkgroten Apr 03 '19 at 09:57
  • as per the above comment, your itterater has exhausted all iterations and can't find a value that meets the condition. You should consider adding a default value into your `next` - `page_number = next((conditional stuff....), 0)` notice the `, 0` after the first arg in next. That will stop you recieving stopiterations but leave you with a default value. – Giannis Katsini Apr 03 '19 at 10:01
  • @dirkgroten I understand pretty well, but I'm asking How I can pick up the value `page_number` which corresponds to the sublist index containing the specific code (I have the id so it's easy to get code). – Essex Apr 03 '19 at 10:02
  • 2
    `pk` is the `id` of the object you're looking for (an integer), but `value` is the object's code (a string), so you'll never meet the requirement `pk in value`. You should change your objects list to be tuples containing id and code (.values_list('pk', 'code')) so that the `value` in your test is the tuple and you can check `pk == value[0]` – dirkgroten Apr 03 '19 at 10:08
  • 1
    but whether then you use `next` or use `[0]` (to get the first element) you should `try...except` because the list might not contain a matching object (if pk isn't found in the db) – dirkgroten Apr 03 '19 at 10:09
  • @dirkgroten It's exaclty what I tried 10s ago !! It works now because it was a mistake from myself ! I edit my question in 15s – Essex Apr 03 '19 at 10:11
  • There is a get or 404 that come in hand in this cases – geckos Apr 03 '19 at 10:54

0 Answers0