Skip to content

Commit

Permalink
Merge pull request #172 from rpkilby/exclude-request-interaction
Browse files Browse the repository at this point in the history
Prevent deepcopying of filter's parent
  • Loading branch information
philipn authored Jun 7, 2017
2 parents ac68223 + 08d518d commit 189e613
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 4 deletions.
10 changes: 7 additions & 3 deletions rest_framework_filters/filterset.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,9 +115,13 @@ def expand_filters(self):

# include exclusion keys
if exclude_name in self.data:
f = copy.deepcopy(f)
f.exclude = not f.exclude
requested_filters[exclude_name] = f
# deepcopy the *base* filter to prevent copying of model & parent
f_copy = copy.deepcopy(self.base_filters[filter_name])
f_copy.parent = f.parent
f_copy.model = f.model
f_copy.exclude = not f.exclude

requested_filters[exclude_name] = f_copy

# include filters from related subsets
if isinstance(f, filters.RelatedFilter) and filter_name in related_data:
Expand Down
35 changes: 34 additions & 1 deletion tests/test_filterset.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
from __future__ import absolute_import
from __future__ import unicode_literals

import sys

from django.test import TestCase
from django.utils import six

Expand All @@ -11,7 +13,7 @@
from django_filters.filters import BaseInFilter

from .testapp.models import (
User, Note, Post, Person, Tag, BlogPost,
Note, Post, Person, Tag, BlogPost,
)

from .testapp.filters import (
Expand All @@ -24,6 +26,21 @@
BlogPostOverrideFilter,
)

from rest_framework.views import APIView
from rest_framework.test import APIRequestFactory
factory = APIRequestFactory()


class limit_recursion:
def __init__(self):
self.original_limit = sys.getrecursionlimit()

def __enter__(self):
sys.setrecursionlimit(100)

def __exit__(self, *args):
sys.setrecursionlimit(self.original_limit)


class LookupsFilterTests(TestCase):
"""
Expand Down Expand Up @@ -429,3 +446,19 @@ def test_related_exclusion_results(self):

self.assertEqual(len(results), 1)
self.assertEqual(results[0], 'Post 2')

def test_exclude_and_request_interaction(self):
# See: https://github.com/philipn/django-rest-framework-filters/issues/171
request = APIView().initialize_request(factory.get('/?tags__name__contains!=Tag'))
filterset = BlogPostFilter(request.query_params, request=request, queryset=BlogPost.objects.all())

try:
with limit_recursion():
qs = filterset.qs
except RuntimeError:
self.fail('Recursion limit reached')

results = [r.title for r in qs]

self.assertEqual(len(results), 1)
self.assertEqual(results[0], 'Post 2')

0 comments on commit 189e613

Please sign in to comment.