Solved - django for-loop only displaying the last iteration

I'm building a book recommendation Django application. I'm done integrating my machine learning model but the problem is that it gets the data from the csv file i used, not from my database. I have no problem displaying the titles of the recommended books but I would like to let the users view the details page of the said book. With that being said, I need to get the id of the recommended books from my Book model.

I'm relatively new to Django so please excuse if my codes are messy.

This is the excerpt from my views.py:

def s_detail(request, book_id): #student paper detail
    cosine_sim = joblib.load('cosine_sim-v5.pkl') #load the ml model 
    data = pd.read_csv('try.csv', sep=',', encoding='utf-8')
    try:
        book = Book.objects.get(pk=book_id)
        fav = True 
        if book.favorites.filter(id=request.user.id).exists():
            fav=False
    
        def recommendations(book_id,n, cosine_sim = cosine_sim):
            recommended_books = []
            idx = book_id
            score_series = pd.Series(cosine_sim[idx]).sort_values(ascending = False)
            top_n_indexes = list(score_series.iloc[1:n+1].index)
            for i in top_n_indexes:
                recommended_books.append(list(data.index)[i]) # data.index for book_id column
            return recommended_books

        recommend = recommendations(book_id, 3) 
        for i in recommend: 
            new = Book.objects.filter(id=i) #to get the Book id from the model 
            print(new) #just to check if it's working

    except Book.DoesNotExist: 
        raise Http404("Title does not exist")    
    return render (request, 'books/s_detail.html', {'book':book, 'fav':fav, 'recommend':recommend, 'new':new}) 

in my template:

{% for book in new %}
    <div class="card">     
      <img src="/books/media/{{book.book_image}}" alt="bookimage"><br>
        <div class="browse-content">
            <b>Title:</b> <a href="{% url 's_detail' book.id %}"> {{book.book_title}} </a><br>
            <div class="eye">
                <i class="fa-solid fa-eye"></i> Views
            </div>
        </div>
    </div>
{% endfor %}

the iteration works fine based on the printed output in the terminal

[22/Dec/2022 10:27:42] "GET /books/s_browse HTTP/1.1" 200 27157
<QuerySet [<Book: Radioprotective Potential of Leaf Extract of Sapinit (Rubus rosifolius) On the Sperm Count and Sperm Morphology of y-Irradiated Mice (Mus musculus)>]>
<QuerySet [<Book: Analysis of Cytotoxic Activities of Select Plant Extracts against A549 - Lung Adenocarcinoma Cell Line>]>
<QuerySet [<Book: Inventory of Epiphytes on the Walls of Intramuros, Manila>]>

but only displays the last iteration in the template

I feel like I need to store the values somewhere but I don't know how.

You are overwriting the new variable with a new QuerySet of size 1 in your for loop. Try replacing the following:

recommend = recommendations(book_id, 3) 
for i in recommend: 
    new = Book.objects.filter(id=i) #to get the Book id from the model 
    print(new) #just to check if it's working

with this:

recommend = recommendations(book_id, 3) 
new = Book.objects.filter(id__in=recommend)
print(new)

This will fetch all Book instances with an id value that exists in the recommend list.

Back to Top