0

I am using Django filters and when I apply the filters they work but when I go to the next page of results they reset. I have looked at this post django-filter use paginations but they seem to be doing the same things that I am. What am I doing wrong?

Url

url(r'^relations/$', views.annotation_views.relations, name="relations")

returns a url like this when the filters are applied:

/relations/?createdBy=&occursIn=&createdAfter=&createdBefore=&terminal_nodes=&project=

Filters.py

class RelationSetFilter(django_filters.FilterSet):
    occursIn = django_filters.CharFilter('occursIn__uri', method='filter_occursIn')
    createdBefore = django_filters.DateTimeFilter('created', lookup_expr='lt')
    createdAfter = django_filters.DateTimeFilter('created', lookup_expr='gt')

    terminal_nodes = django_filters.CharFilter('terminal_nodes__uri')


    def filter_occursIn(self, queryset, name, value):
        if not value:
            return queryset
        return queryset.filter(Q(occursIn__uri=value) | Q(occursIn__part_of__uri=value) | Q(occursIn__part_of__part_of__uri=value))

    class Meta:
        model = RelationSet
        fields = ['createdBy', 'project', 'occursIn', 'terminal_nodes']

View

def relations(request):
    from annotations.filters import RelationSetFilter

    qs = RelationSet.objects.all()
    filtered = RelationSetFilter(request.GET, queryset=qs)
    qs = filtered.qs
    for r in qs:
        print r.__dict__

    paginator = Paginator(qs, 40)
    page = request.GET.get('page')
    try:
        relations = paginator.page(page)
    except PageNotAnInteger:
        # If page is not an integer, deliver first page.
        relations = paginator.page(1)
    except EmptyPage:
        # If page is out of range (e.g. 9999), deliver last page of results.
        relations = paginator.page(paginator.num_pages)

    context = {
        'paginator': paginator,
        'relations': relations,
        'params': request.GET.urlencode(),
        'filter': filtered,
    }
    return render(request, 'annotations/relations.html', context)
Taylor
  • 1,223
  • 1
  • 15
  • 30

1 Answers1

-1

I was able to solve this by copying the url and passing the params to the template. I had to delete the page param due to it being duplicated. In order to do this I added the following:

View

def relations(request):
    from annotations.filters import RelationSetFilter

    qs = RelationSet.objects.all()
    filtered = RelationSetFilter(request.GET, queryset=qs)
    qs = filtered.qs
    for r in qs:
        print r.__dict__

    paginator = Paginator(qs, 40)
    page = request.GET.get('page')

    gt = request.GET.copy()
    if 'page' in gt:
        del gt['page']

    try:
        relations = paginator.page(page)
    except PageNotAnInteger:
        # If page is not an integer, deliver first page.
        relations = paginator.page(1)
    except EmptyPage:
        # If page is out of range (e.g. 9999), deliver last page of results.
        relations = paginator.page(paginator.num_pages)

    context = {
        'paginator': paginator,
        'relations': relations,
        'params': urlencode(gt),
        'filter': filtered,
        }
    return render(request, 'annotations/relations.html', context)

Template

<div class="col-xs-4  clearfix text-center">
            {% if relations.has_next %}
            <div class="pull-right">
                <a href="?page={{ relations.next_page_number }}&{{ params }}">Next &raquo;</a>
            </div>
            {% endif %}
        </div>

Update

I found a more secure fix for this by getting the data directly for the filter object

project = filtered.data.get('project')

then adding this to the view

&project={{ project }}
Taylor
  • 1,223
  • 1
  • 15
  • 30