Search code examples
djangodjango-rest-frameworkdjango-formsdjango-viewsdjango-pagination

Queried Results from Database Disappear on Pagination: Django


I am new to using the Django framework. I am creating a form to take in User input to query a database. I want to display the queried results on the same page, below the from fields. I am able to do the same. However, upon implementing Pagination, and clicking the 'next' link, or trying to sort the results using 'order_by', the queried results disappear from the webpage. How can this be resolved? Below are my code files:\ views.py:

    def get(self, request, *args, **kwargs):
        paginated_objects = []
        order_by = None
        form = QueryForm(request.GET)
        button_state = True
        if form.is_valid():
            max_traj_len = form.data["traj_len_user"]
            print(form.data["submit"])
            print(max_traj_len)
            order_by = request.GET.get('order_by', 'traj_len')  ##default order_by is set here
            backtrack_flag = form.data["backtrack_user"]
            print(backtrack_flag)
            queried_objects = list(collection.find({'traj_len':{'$lte':int(max_traj_len)}}))
            paginator = Paginator(queried_objects, 25)
            page = request.GET.get('page')
            paginated_objects = paginator.get_page(page)
            button_state = request.GET.get('submit')

        return render(request, self.template_name, {'form': form,'object_list': paginated_objects, 'order_by': order_by, 'button_state': button_state})

template.html:

{% extends 'base.html' %}

{% block content %}
<form action='' method='get'>
{%  csrf_token %}
    <table>{{ form.as_table }}</table>
    <input type="submit" name="submit" value="Query">
</form>
    {% if button_state == 'Query' %}
    <table id="studata">
    <thead>
    <th><a href="?order_by=traj_id">Traj ID</a></th>
    <th><a href="?order_by=traj_path">Traj Path</a></th>
    <th><a href="?order_by=traj_len">Traj Length</a></th>
    <th><a href="?order_by=interpolated_id">Interpolated_ID</a></th>
    <th><a href="?order_by=inter_path">Interpolated Path</a></th>
    <th><a href="?order_by=inter_path_len">Interpolated Path Length</a></th>
    <th><a href="?order_by=backtrack">Backtrack</a></th>
    <th><a href="?order_by=reached_goal">Reached Goal</a></th>
    </thead>
    {% for obj in object_list %}<tr>
    <script type="text/javascript">
    var ele = {{ obj.traj_path }};
    var last_ele = ele.pop()
    //assuming 0 is the goal trajectory: change if another json is the goal state
    if(last_ele == 0){
        goal = "True"
    }
    else{
        goal = "False"
    }
    </script>
    <td><a href = '/hoc4/{{ obj.traj_id }}' >{{ obj.traj_id }}</a></td>
    <td>{{ obj.traj_path }}</td>
    <td>{{ obj.traj_len }}</td>
    <td>{{ obj.interpolated_id }}</td>
    <td>{{ obj.inter_path }}</td>
    <td>{{ obj.inter_path_len }}</td>
    <td>{{ obj.backtrack }}</td>
    <td><script type="text/javascript">
        document.write(goal)
      </script>
    </td>
    </tr>
    {% endfor %}
    </table>
    <div class="pagination">
    <span class="step-links">
        {% if object_list.has_previous %}
            <a href="?page=1">&laquo; first</a>
            <a href="?page={{ object_list.previous_page_number }}&order_by={{ order_by }}">previous</a>
        {% endif %}

        <span class="current">
            Page {{ object_list.number }} of {{ object_list.paginator.num_pages }}.
        </span>

        {% if object_list.has_next %}
            <a href="?page={{ object_list.next_page_number }}&order_by={{ order_by }}">next</a>
            <a href="?page={{ object_list.paginator.num_pages }}&order_by={{ order_by }}">last &raquo;</a>
        {% endif %}
    </span>
    </div>
    {% endif %}
{%  endblock %}

forms.py:

class QueryForm(forms.Form):
    traj_len_user = forms.IntegerField(min_value=0, required=True)
    backtrack_user = forms.BooleanField()

Solution

  • You're doing a lot of extra stuff that seems like you don't even need... You don't need a form for querying anything. You only need whatever's in request.GET and request.POST. You can access them by request.GET.get('name_attribute_of_input'), and so on.

    Here's the relevant portion of how to use a Paginator class.

    from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
    
    def get_something(request):
        object_list = MyModel.published.all()
        tag = None
        paginator = Paginator(object_list, 3)  # 3 objects on each page
        page = request.GET.get('page')  # this is getting the 'page' quesry string argument in the url as a GET request, so   ?page=whatever_url
        try:
            my_models = paginator.page(page)  # by itself without paginator, object_list would get all my_models and put it on one page. But the paginator object here converts the X objects into pages.
            # And those pages are reached by the page variable above that GET's it.
        except PageNotAnInteger:
            # If page is not an integer, deliver the 1st page
            my_models = paginator.page(1)
        except EmptyPage:
            # If page is out of range deliver last page of results
            my_models = paginator.page(paginator.num_pages)
        return render(request, 'blog_app/list.html', {'page': page, 'my_models': my_models})
    

    And your template would have something like this in it:

      {% if page.has_previous %}
        <a href="?page={{ page.previous_page_number }}">Previous</a>
      {% endif %}
    
      <span class="current">
        Page {{ page.number }} of {{ page.paginator.num_pages }}.
      </span>
    
      {% if page.has_next %}
        <a href="?page={{ page.next_page_number }}">Next</a>
      {% endif %}