1

I'm working on To-Do App. I have two kinds of data,

  1. Upcoming To-do Item and
  2. Completed To-do Items.

So, I'm filtering data in views.py as upcoming items and completed items. I want to display them on the same page using pagination. I'm getting result too but if upcoming item completed in page-1 I was unable to visit page-2 because upcoming item for page-2 was empty, but I have items on completed items. I couldn't see that.

views.py

@login_required(login_url='login')
def home(request):

    todo_form = TodoForm()
    current = timezone.now()

    todo_items_upcoming = Todo.objects.filter(user_id=request.user, completed=False).order_by('-date_created')

    todo_items_completed = Todo.objects.filter(user_id=request.user, completed=True)

    pagi1 = Paginator(todo_items_upcoming, 4)
    pagi2 = Paginator(todo_items_completed, 4)

    page_num = request.GET.get('page')
    page_num2 = request.GET.get('page')

    page_obj = pagi1.get_page(page_num)
    page_obj2 = pagi2.get_page(page_num2)

    if request.method == "POST":
        todo_form = TodoForm(request.POST)
        if todo_form.is_valid():
            data = todo_form.cleaned_data.get('title')

            obj = Todo.objects.create(date_created=current, title=data, user_id=request.user)

    context = {'todo_form':todo_form, 'page_obj':page_obj, 'page_obj2':page_obj2}
    return render(request, 'todo/main.html', context)

main.html

{% extends 'todo/index.html' %}
{% load crispy_forms_tags %}


{% block content %}

    <nav aria-label="...">
        <ul class="pagination justify-content-center">

            <!-- pagination - previous pages -->
            {% if page_obj.has_previous or page_obj2.has_previous %}

                <li class="page-item">
                    {% if page_obj.has_previous %}

                        <a class="page-link" href="?page={{ page_obj.previous_page_number }}" tabindex="-1">&laquo;</a>
                    
                    {% else %}

                        <a class="page-link" href="?page={{ page_obj2.previous_page_number }}" tabindex="-1">&laquo;</a>

                    {% endif %}
                </li>

            {% endif %}

            <!-- pagination - current page -->
            <li class="page-item active">
                <a class="page-link" href="?page={{ page_obj.number }}">{{ page_obj.number }}</a>
            </li>

            <!-- pagination - Next pages -->
            {% if page_obj.has_next or page_obj2.has_next %}

                <li class="page-item">
                    {% if page_obj.has_next %}

                        <a class="page-link" href="?page={{ page_obj.next_page_number }}">&raquo;</a>
                    
                    {% else %}

                        <a class="page-link" href="?page={{ page_obj2.next_page_number }}">&raquo;</a>

                    {% endif %}
                </li>

            {% endif %}


        </ul>
    </nav>


    <div class="center-column">

        <h2 class="heading" style="text-align: center;">Hello {{ request.user.username }}, Here's your ToDo List</h2>
        
        <form action="" method="POST" id='form-create'>
            {% csrf_token %}
            <div style="text-align: center;">

                {{ todo_form.title }}
                
                <button type="submit" class="form-control btn btn-primary mb-3 mr-sm-2">Add Items</button>

            </div>
            
        </form>


        <h4 class="heading" style="text-align: center;">Upcoming ToDo Items</h4><br>
        <div class="row">
            <div class="col" id="upcomItem">
                <ul class="list-group" id="upcomingItems">

                    {% for i in page_obj %}

                        <li class="list-group-item list-group-item-primary mb-2" id="upcomingItem">{{ i.title }}

                            <div class="float-right">

                                <button type="submit" class="btn-sm btn-danger ml-2 mt-2 mr-2 mb-1"><a href="{% url 'delete_todo' i.id %}">Delete</a></button>
                                
                            </div>

                            <div class="float-right">

                                <button type="submit" class="btn-sm btn-success ml-2 mt-2 mr-2 mb-1" id="update_btn"><a href="{% url 'update_todo' i.id %}">Update</a></button>

                            </div>

                            <div class="float-right">
                        
                                <button type="submit" class="btn-sm btn-dark ml-2 mt-2 mr-2 mb-1" id="completed_btn"><a href="{% url 'completed_todo' i.id %}">Completed</a></button>

                            </div>              
                                        
                        </li>
                            
                    {% endfor %}

                </ul>
            </div>
        </div>

        <hr style="border-top: 1px solid #999; ">
        <div class="row">
            <div class="col">
                <h4 class="heading" style="text-align: center;">Completed ToDo Items</h4>
                <ul class="list-group" id='compItems'>


                    {% for i in page_obj2 %}<hr>

                        <li class="list-group-item list-group-item-primary mb-2" id="upcomingItem">{{ i.title }}

                        <div class="float-right">

                            <button type="submit" class="btn-sm btn-danger ml-2 mt-2 mr-2 mb-1"><a href="{% url 'delete_todo' i.id %}">Delete</a></button>
                                
                        </div>                              

                        <div class="float-right">

                            <button type="submit" class="btn-sm btn-success ml-2 mt-2 mr-2 mb-1" ><a href="{% url 'update_todo' i.id %}">Update</a></button>

                        </div>
                        </li>
                    {% endfor %}

                </ul>
            </div>
        </div>

    </div>

{% endblock %}

At first I have used or in template tags in if condition I got this error. Error Message occurs when I try to add new to-do item Error Message occurs when I try to add new to-do item

I tried and operator in template tags I didn;'t even get page-2 link eventhough I have upcoming items and no extra completed items.

goku10
  • 65
  • 1
  • 9

2 Answers2

0

Your conditions should be a disjunction of the conditions of the paginators, so or instead of and:

{% if page_obj.has_previous or page_obj2.has_previous %}
    …
{% endif %}

the same for .has_next. The previous and next page then should be handled by checking which page object has a next page, so:

{% if page_obj.has_next or page_obj2.has_next %}
    <li class="page-item">
        {% if page_obj.has_next %}
            <a class="page-link" href="?page={{ page_obj.next_page_number }}">&raquo;</a>
        {% else %}
<a class="page-link" href="?page={{ page_obj2.next_page_number }}">&raquo;</a>
        {% endif %}
    </li>
{% endif %}

That being said, I'm not sure this provides the best user experience. Perhaps it is better to make two separate paginations (so work with ?pagedone=…&pagetodo=…).

Willem Van Onsem
  • 443,496
  • 30
  • 428
  • 555
  • I have used `or` in template tag I got **Empty page error**. When I used `and` operator in template tag If any of the List upcoming Items or Completed Items have no item in second page I'm not getting page-2 link in pagination. – goku10 Feb 21 '21 at 06:19
  • @goku_cv: yes, you will need to check what paginator has a next page, and update accordingly. See edit. – Willem Van Onsem Feb 21 '21 at 07:35
  • I have updated like you said. Items per page was 4 for upcoming Items and completed Items so, totally 8. If there are only 4 upcoming items and 6 completed items, the page link was changing, but the content remains the same as the first page. I'm unable to see the remaining 2 items of completed Items. And If I have more 5 upcoming and 6 completed then I'm able to view the Items that corresponding to page-2. – goku10 Feb 21 '21 at 08:48
  • @goku_cv: how do you *render* the items? – Willem Van Onsem Feb 21 '21 at 08:52
  • I have iterated from page_obj and page_obj to display in html. I have provided full html code. – goku10 Feb 21 '21 at 12:33
0

Use or operator as @Willem pointed. And you active link href must be {{ page_obj.number }} instead {{ page_obj.page_number }}:

<li class="page-item active">
    <a class="page-link" href="?page={{ page_obj.number }}">{{ page_obj.number }}</a>
</li>

As you can see your error EmptyPage raised in your template at line 18

NKSM
  • 5,422
  • 4
  • 25
  • 38