added new tests and refactored some previous tests

* removed tests that essentially covered form/field rendering
* added more edge-case tests (Proxy models, MTI models, filtering through relationships)
* moved most of the tests which performed queryset filtering to new filtering_tests.py
* added "pragma: nocover" in a few places for coverage.py to omit for reporting
* included fix for generic view error inside of ImproperlyConfigured handler
This commit is contained in:
nkryptic 2013-02-26 02:45:30 -05:00
parent ea2e1fc61c
commit ec169c901c
10 changed files with 1222 additions and 1637 deletions

View File

@ -13,7 +13,8 @@ from django.utils.text import capfirst
try:
from django.db.models.constants import LOOKUP_SEP
except ImportError: # Django < 1.5 fallback
except ImportError: # pragma: nocover
# Django < 1.5 fallback
from django.db.models.sql.constants import LOOKUP_SEP # noqa
from .filters import (Filter, CharFilter, BooleanFilter,

View File

@ -48,7 +48,8 @@ class FilterMixin(object):
msg = ("'%s' does not define a 'model' and the view '%s' does "
"not return a valid queryset from 'get_queryset'. You "
"must fix one of them.")
raise ImproperlyConfigured(msg % self.__class__.__name__)
args = (filterset_class.__name__, self.__class__.__name__)
raise ImproperlyConfigured(msg % args)
return kwargs

View File

@ -12,7 +12,7 @@ from django.db.models.fields import BLANK_CHOICE_DASH
from django.forms.widgets import flatatt
try:
from django.utils.encoding import force_text
except:
except: # pragma: nocover
from django.utils.encoding import force_unicode as force_text # noqa
from django.utils.safestring import mark_safe
from django.utils.translation import ugettext as _

View File

@ -23,6 +23,7 @@ from django_filters.filters import NumberFilter
from django_filters.filters import RangeFilter
from django_filters.filters import DateRangeFilter
from django_filters.filters import AllValuesFilter
from django_filters.filters import LOOKUP_TYPES
class FilterTests(TestCase):
@ -41,15 +42,24 @@ class FilterTests(TestCase):
field = f.field
self.assertIsInstance(field, forms.Field)
def test_field_with_single_lookup_type(self):
f = Filter(lookup_type='iexact')
field = f.field
self.assertIsInstance(field, forms.Field)
def test_field_with_none_lookup_type(self):
f = Filter(lookup_type=None)
field = f.field
self.assertIsInstance(field, LookupTypeField)
choice_field = field.fields[1]
self.assertEqual(len(choice_field.choices), len(LOOKUP_TYPES))
def test_field_with_list_lookup_type(self):
f = Filter(lookup_type=('istartswith', 'iendswith'))
field = f.field
self.assertIsInstance(field, LookupTypeField)
choice_field = field.fields[1]
self.assertEqual(len(choice_field.choices), 2)
def test_field_params(self):
with mock.patch.object(Filter, 'field_class',
@ -267,6 +277,7 @@ class ModelChoiceFilterTests(TestCase):
f = ModelChoiceFilter(queryset=qs)
field = f.field
self.assertIsInstance(field, forms.ModelChoiceField)
self.assertEqual(field.queryset, qs)
class ModelMultipleChoiceFilterTests(TestCase):
@ -281,6 +292,7 @@ class ModelMultipleChoiceFilterTests(TestCase):
f = ModelMultipleChoiceFilter(queryset=qs)
field = f.field
self.assertIsInstance(field, forms.ModelMultipleChoiceField)
self.assertEqual(field.queryset, qs)
class NumberFilterTests(TestCase):

View File

@ -0,0 +1,972 @@
from __future__ import absolute_import
from __future__ import unicode_literals
import mock
import datetime
from django.utils import unittest
from django.test import TestCase
from django.utils import six
from django.utils.timezone import now
from django.utils import timezone
from django_filters.filterset import FilterSet
from django_filters.filters import AllValuesFilter
from django_filters.filters import CharFilter
from django_filters.filters import ChoiceFilter
from django_filters.filters import DateRangeFilter
# from django_filters.filters import DateTimeFilter
from django_filters.filters import MultipleChoiceFilter
from django_filters.filters import NumberFilter
from django_filters.filters import RangeFilter
# from django_filters.widgets import LinkWidget
from .models import User
from .models import Comment
from .models import Book
# from .models import Restaurant
from .models import Article
# from .models import NetworkSetting
# from .models import SubnetMaskField
from .models import Company
from .models import Location
from .models import Account
from .models import Profile
from .models import STATUS_CHOICES
class CharFilterTests(TestCase):
def test_filtering(self):
b1 = Book.objects.create(
title="Ender's Game", price='1.00', average_rating=3.0)
b2 = Book.objects.create(
title="Rainbow Six", price='1.00', average_rating=3.0)
b3 = Book.objects.create(
title="Snowcrash", price='1.00', average_rating=3.0)
class F(FilterSet):
class Meta:
model = Book
fields = ['title']
qs = Book.objects.all()
f = F(queryset=qs)
self.assertQuerysetEqual(f.qs, [b1.pk, b2.pk, b3.pk],
lambda o: o.pk, ordered=False)
f = F({'title': 'Snowcrash'}, queryset=qs)
self.assertQuerysetEqual(f.qs, [b3.pk], lambda o: o.pk)
class BooleanFilterTests(TestCase):
def test_filtering(self):
User.objects.create(username='alex', is_active=False)
User.objects.create(username='jacob', is_active=True)
User.objects.create(username='aaron', is_active=False)
class F(FilterSet):
class Meta:
model = User
fields = ['is_active']
qs = User.objects.all()
# '2' and '3' are how the field expects the data from the browser
f = F({'is_active': '2'}, queryset=qs)
self.assertQuerysetEqual(f.qs, ['jacob'], lambda o: o.username, False)
f = F({'is_active': '3'}, queryset=qs)
self.assertQuerysetEqual(f.qs,
['alex', 'aaron'],
lambda o: o.username, False)
f = F({'is_active': '1'}, queryset=qs)
self.assertQuerysetEqual(f.qs,
['alex', 'aaron', 'jacob'],
lambda o: o.username, False)
class ChoiceFilterTests(TestCase):
def test_filtering(self):
User.objects.create(username='alex', status=1)
User.objects.create(username='jacob', status=2)
User.objects.create(username='aaron', status=2)
User.objects.create(username='carl', status=0)
class F(FilterSet):
class Meta:
model = User
fields = ['status']
f = F()
self.assertQuerysetEqual(f.qs,
['aaron', 'alex', 'jacob', 'carl'],
lambda o: o.username, False)
f = F({'status': '1'})
self.assertQuerysetEqual(f.qs, ['alex'], lambda o: o.username, False)
f = F({'status': '2'})
self.assertQuerysetEqual(f.qs, ['jacob', 'aaron'],
lambda o: o.username, False)
f = F({'status': '0'})
self.assertQuerysetEqual(f.qs, ['carl'], lambda o: o.username, False)
class MultipleChoiceFilterTests(TestCase):
def test_filtering(self):
User.objects.create(username='alex', status=1)
User.objects.create(username='jacob', status=2)
User.objects.create(username='aaron', status=2)
User.objects.create(username='carl', status=0)
class F(FilterSet):
status = MultipleChoiceFilter(choices=STATUS_CHOICES)
class Meta:
model = User
fields = ['status']
qs = User.objects.all().order_by('username')
f = F(queryset=qs)
self.assertQuerysetEqual(
f.qs, ['aaron', 'jacob', 'alex', 'carl'],
lambda o: o.username, False)
f = F({'status': ['0']}, queryset=qs)
self.assertQuerysetEqual(
f.qs, ['carl'], lambda o: o.username)
f = F({'status': ['0', '1']}, queryset=qs)
self.assertQuerysetEqual(
f.qs, ['alex', 'carl'], lambda o: o.username)
f = F({'status': ['0', '1', '2']}, queryset=qs)
self.assertQuerysetEqual(
f.qs, ['aaron', 'alex', 'carl', 'jacob'], lambda o: o.username)
class DateFilterTests(TestCase):
def test_filtering(self):
today = now().date()
timestamp = now().time().replace(microsecond=0)
last_week = today - datetime.timedelta(days=7)
check_date = six.text_type(last_week)
u = User.objects.create(username='alex')
Comment.objects.create(author=u, time=timestamp, date=today)
Comment.objects.create(author=u, time=timestamp, date=last_week)
Comment.objects.create(author=u, time=timestamp, date=today)
Comment.objects.create(author=u, time=timestamp, date=last_week)
class F(FilterSet):
class Meta:
model = Comment
fields = ['date']
f = F({'date': check_date}, queryset=Comment.objects.all())
self.assertEqual(len(f.qs), 2)
self.assertQuerysetEqual(f.qs, [2, 4], lambda o: o.pk)
class TimeFilterTests(TestCase):
def test_filtering(self):
today = now().date()
now_time = now().time().replace(microsecond=0)
ten_min_ago = (now() - datetime.timedelta(minutes=10))
fixed_time = ten_min_ago.time().replace(microsecond=0)
check_time = six.text_type(fixed_time)
u = User.objects.create(username='alex')
Comment.objects.create(author=u, time=now_time, date=today)
Comment.objects.create(author=u, time=fixed_time, date=today)
Comment.objects.create(author=u, time=now_time, date=today)
Comment.objects.create(author=u, time=fixed_time, date=today)
class F(FilterSet):
class Meta:
model = Comment
fields = ['time']
f = F({'time': check_time}, queryset=Comment.objects.all())
self.assertEqual(len(f.qs), 2)
self.assertQuerysetEqual(f.qs, [2, 4], lambda o: o.pk)
class DateTimeFilterTests(TestCase):
def test_filtering(self):
now_dt = now()
ten_min_ago = now_dt - datetime.timedelta(minutes=10)
one_day_ago = now_dt - datetime.timedelta(days=1)
u = User.objects.create(username='alex')
Article.objects.create(author=u, published=now_dt)
Article.objects.create(author=u, published=ten_min_ago)
Article.objects.create(author=u, published=one_day_ago)
tz = timezone.get_current_timezone()
# make naive, like a browser would send
local_ten_min_ago = timezone.make_naive(ten_min_ago, tz)
check_dt = six.text_type(local_ten_min_ago)
class F(FilterSet):
class Meta:
model = Article
fields = ['published']
qs = Article.objects.all()
f = F({'published': ten_min_ago}, queryset=qs)
self.assertEqual(len(f.qs), 1)
self.assertQuerysetEqual(f.qs, [2], lambda o: o.pk)
# this is how it would come through a browser
f = F({'published': check_dt}, queryset=qs)
self.assertEqual(len(f.qs), 1,
"%s isn't matching %s when cleaned" % (check_dt, ten_min_ago))
self.assertQuerysetEqual(f.qs, [2], lambda o: o.pk)
class ModelChoiceFilterTests(TestCase):
def test_filtering(self):
alex = User.objects.create(username='alex')
jacob = User.objects.create(username='jacob')
date = now().date()
time = now().time()
Comment.objects.create(author=jacob, time=time, date=date)
Comment.objects.create(author=alex, time=time, date=date)
Comment.objects.create(author=jacob, time=time, date=date)
class F(FilterSet):
class Meta:
model = Comment
fields = ['author']
qs = Comment.objects.all()
f = F({'author': jacob.pk}, queryset=qs)
self.assertQuerysetEqual(f.qs, [1, 3], lambda o: o.pk)
class ModelMultipleChoiceFilterTests(TestCase):
def setUp(self):
alex = User.objects.create(username='alex')
User.objects.create(username='jacob')
aaron = User.objects.create(username='aaron')
b1 = Book.objects.create(title="Ender's Game", price='1.00',
average_rating=3.0)
b2 = Book.objects.create(title="Rainbow Six", price='1.00',
average_rating=3.0)
b3 = Book.objects.create(title="Snowcrash", price='1.00',
average_rating=3.0)
Book.objects.create(title="Stranger in a Strage Land", price='1.00',
average_rating=3.0)
alex.favorite_books = [b1, b2]
aaron.favorite_books = [b1, b3]
def test_filtering(self):
class F(FilterSet):
class Meta:
model = User
fields = ['favorite_books']
qs = User.objects.all().order_by('username')
f = F({'favorite_books': ['1']}, queryset=qs)
self.assertQuerysetEqual(f.qs, ['aaron', 'alex'], lambda o: o.username)
f = F({'favorite_books': ['1', '3']}, queryset=qs)
self.assertQuerysetEqual(f.qs, ['aaron', 'alex'], lambda o: o.username)
f = F({'favorite_books': ['2']}, queryset=qs)
self.assertQuerysetEqual(f.qs, ['alex'], lambda o: o.username)
f = F({'favorite_books': ['4']}, queryset=qs)
self.assertQuerysetEqual(f.qs, [], lambda o: o.username)
class NumberFilterTests(TestCase):
def setUp(self):
Book.objects.create(title="Ender's Game", price='10.0',
average_rating=4.7999999999999998)
Book.objects.create(title="Rainbow Six", price='15.0',
average_rating=4.5999999999999996)
Book.objects.create(title="Snowcrash", price='20.0',
average_rating=4.2999999999999998)
def test_filtering(self):
class F(FilterSet):
class Meta:
model = Book
fields = ['price']
f = F({'price': 10}, queryset=Book.objects.all())
self.assertQuerysetEqual(f.qs, ['Ender\'s Game'], lambda o: o.title)
def test_filtering_with_single_lookup_type(self):
class F(FilterSet):
price = NumberFilter(lookup_type='lt')
class Meta:
model = Book
fields = ['price']
f = F({'price': 16}, queryset=Book.objects.all().order_by('title'))
self.assertQuerysetEqual(
f.qs, ['Ender\'s Game', 'Rainbow Six'], lambda o: o.title)
def test_filtering_with_multiple_lookup_types(self):
class F(FilterSet):
price = NumberFilter(lookup_type=['lt', 'gt'])
class Meta:
model = Book
fields = ['price']
qs = Book.objects.all()
f = F({'price_0': '15', 'price_1': 'lt'}, queryset=qs)
self.assertQuerysetEqual(f.qs, ['Ender\'s Game'], lambda o: o.title)
f = F({'price_0': '15', 'price_1': 'lt'})
self.assertQuerysetEqual(f.qs, ['Ender\'s Game'], lambda o: o.title)
f = F({'price_0': '', 'price_1': 'lt'})
self.assertQuerysetEqual(f.qs,
['Ender\'s Game', 'Rainbow Six', 'Snowcrash'],
lambda o: o.title, ordered=False)
class F(FilterSet):
price = NumberFilter(lookup_type=['lt', 'gt', 'exact'])
class Meta:
model = Book
fields = ['price']
f = F({'price_0': '15'})
self.assertQuerysetEqual(f.qs, ['Rainbow Six'], lambda o: o.title)
class RangeFilterTests(TestCase):
def setUp(self):
Book.objects.create(title="Ender's Game", price='10.0',
average_rating=4.7999999999999998)
Book.objects.create(title="Rainbow Six", price='15.0',
average_rating=4.5999999999999996)
Book.objects.create(title="Snowcrash", price='20.0',
average_rating=4.2999999999999998)
def test_filtering(self):
class F(FilterSet):
price = RangeFilter()
class Meta:
model = Book
fields = ['price']
qs = Book.objects.all().order_by('title')
f = F(queryset=qs)
self.assertQuerysetEqual(f.qs,
['Ender\'s Game', 'Rainbow Six', 'Snowcrash'],
lambda o: o.title)
f = F({'price_0': '5', 'price_1': '15'}, queryset=qs)
self.assertQuerysetEqual(f.qs,
['Ender\'s Game', 'Rainbow Six'],
lambda o: o.title)
@unittest.skip('date-range is funky')
class DateRangeFilterTests(TestCase):
def setUp(self):
today = now().date()
five_days_ago = today - datetime.timedelta(days=5)
two_weeks_ago = today - datetime.timedelta(days=14)
two_months_ago = today - datetime.timedelta(days=62)
two_years_ago = today - datetime.timedelta(days=800)
alex = User.objects.create(username='alex')
time = now().time()
Comment.objects.create(date=two_weeks_ago, author=alex, time=time)
Comment.objects.create(date=two_years_ago, author=alex, time=time)
Comment.objects.create(date=five_days_ago, author=alex, time=time)
Comment.objects.create(date=today, author=alex, time=time)
Comment.objects.create(date=two_months_ago, author=alex, time=time)
def test_filtering_for_year(self):
class F(FilterSet):
date = DateRangeFilter()
class Meta:
model = Comment
fields = ['date']
f = F({'date': '4'}) # this year
self.assertQuerysetEqual(f.qs, [1, 3, 4, 5], lambda o: o.pk, False)
def test_filtering_for_month(self):
class F(FilterSet):
date = DateRangeFilter()
class Meta:
model = Comment
fields = ['date']
f = F({'date': '3'}) # this month
self.assertQuerysetEqual(f.qs, [1, 3, 4], lambda o: o.pk, False)
@unittest.expectedFailure
def test_filtering_for_week(self):
class F(FilterSet):
date = DateRangeFilter()
class Meta:
model = Comment
fields = ['date']
f = F({'date': '2'}) # this week
self.assertQuerysetEqual(f.qs, [3, 4], lambda o: o.pk, False)
def test_filtering_for_today(self):
class F(FilterSet):
date = DateRangeFilter()
class Meta:
model = Comment
fields = ['date']
f = F({'date': '1'}) # today
self.assertQuerysetEqual(f.qs, [4], lambda o: o.pk, False)
# it will be difficult to test for TZ related issues, where "today" means
# different things to both user and server.
class AllValuesFilterTests(TestCase):
def test_filtering(self):
User.objects.create(username='alex')
User.objects.create(username='jacob')
User.objects.create(username='aaron')
class F(FilterSet):
username = AllValuesFilter()
class Meta:
model = User
fields = ['username']
self.assertEqual(list(F().qs), list(User.objects.all()))
self.assertEqual(list(F({'username': 'alex'})),
[User.objects.get(username='alex')])
self.assertEqual(list(F({'username': 'jose'})),
list(User.objects.all()))
class O2ORelationshipTests(TestCase):
def setUp(self):
a1 = Account.objects.create(
name='account1', in_good_standing=False, friendly=False)
a2 = Account.objects.create(
name='account2', in_good_standing=True, friendly=True)
a3 = Account.objects.create(
name='account3', in_good_standing=True, friendly=False)
a4 = Account.objects.create(
name='account4', in_good_standing=False, friendly=True)
Profile.objects.create(account=a1, likes_coffee=True, likes_tea=False)
Profile.objects.create(account=a2, likes_coffee=False, likes_tea=True)
Profile.objects.create(account=a3, likes_coffee=True, likes_tea=True)
Profile.objects.create(account=a4, likes_coffee=False, likes_tea=False)
def test_o2o_relation(self):
class F(FilterSet):
class Meta:
model = Profile
fields = ('account',)
f = F()
self.assertEqual(f.qs.count(), 4)
f = F({'account': 1})
self.assertEqual(f.qs.count(), 1)
self.assertQuerysetEqual(f.qs, [1], lambda o: o.pk)
def test_reverse_o2o_relation(self):
with self.assertRaises(AttributeError):
class F(FilterSet):
class Meta:
model = Account
fields = ('profile',)
def test_o2o_relation_attribute(self):
class F(FilterSet):
class Meta:
model = Profile
fields = ('account__in_good_standing',)
f = F()
self.assertEqual(f.qs.count(), 4)
f = F({'account__in_good_standing': '2'})
self.assertEqual(f.qs.count(), 2)
self.assertQuerysetEqual(f.qs, [2, 3], lambda o: o.pk)
def test_o2o_relation_attribute2(self):
class F(FilterSet):
class Meta:
model = Profile
fields = ('account__in_good_standing', 'account__friendly',)
f = F()
self.assertEqual(f.qs.count(), 4)
f = F({'account__in_good_standing': '2', 'account__friendly': '2'})
self.assertEqual(f.qs.count(), 1)
self.assertQuerysetEqual(f.qs, [2], lambda o: o.pk)
def test_reverse_o2o_relation_attribute(self):
class F(FilterSet):
class Meta:
model = Account
fields = ('profile__likes_coffee',)
f = F()
self.assertEqual(f.qs.count(), 4)
f = F({'profile__likes_coffee': '2'})
self.assertEqual(f.qs.count(), 2)
self.assertQuerysetEqual(f.qs, [1, 3], lambda o: o.pk)
def test_reverse_o2o_relation_attribute2(self):
class F(FilterSet):
class Meta:
model = Account
fields = ('profile__likes_coffee', 'profile__likes_tea')
f = F()
self.assertEqual(f.qs.count(), 4)
f = F({'profile__likes_coffee': '2', 'profile__likes_tea': '2'})
self.assertEqual(f.qs.count(), 1)
self.assertQuerysetEqual(f.qs, [3], lambda o: o.pk)
class FKRelationshipTests(TestCase):
def test_fk_relation(self):
company1 = Company.objects.create(name='company1')
company2 = Company.objects.create(name='company2')
Location.objects.create(
company=company1, open_days="some", zip_code="90210")
Location.objects.create(
company=company2, open_days="WEEKEND", zip_code="11111")
Location.objects.create(
company=company1, open_days="monday", zip_code="12345")
class F(FilterSet):
class Meta:
model = Location
fields = ('company',)
f = F()
self.assertEqual(f.qs.count(), 3)
f = F({'company': 1})
self.assertEqual(f.qs.count(), 2)
self.assertQuerysetEqual(f.qs, [1, 3], lambda o: o.pk)
def test_reverse_fk_relation(self):
alex = User.objects.create(username='alex')
jacob = User.objects.create(username='jacob')
date = now().date()
time = now().time()
Comment.objects.create(text='comment 1',
author=jacob, time=time, date=date)
Comment.objects.create(text='comment 2',
author=alex, time=time, date=date)
Comment.objects.create(text='comment 3',
author=jacob, time=time, date=date)
with self.assertRaises(AttributeError):
class F(FilterSet):
class Meta:
model = User
fields = ['comments']
# qs = User.objects.all()
# f = F({'comment': 2}, queryset=qs)
# self.assertQuerysetEqual(f.qs, ['alex'], lambda o: o.username)
with self.assertRaises(AttributeError):
class F(FilterSet):
comment = AllValuesFilter()
class Meta:
model = User
fields = ['comments']
# f = F({'comments': 2}, queryset=qs)
# self.assertQuerysetEqual(f.qs, ['alex'], lambda o: o.username)
def test_fk_relation_attribute(self):
now_dt = now()
alex = User.objects.create(username='alex')
jacob = User.objects.create(username='jacob')
User.objects.create(username='aaron')
Article.objects.create(author=alex, published=now_dt)
Article.objects.create(author=jacob, published=now_dt)
Article.objects.create(author=alex, published=now_dt)
class F(FilterSet):
class Meta:
model = Article
fields = ['author__username']
self.assertEqual(list(F.base_filters), ['author__username'])
self.assertEqual(F({'author__username': 'alex'}).qs.count(), 2)
self.assertEqual(F({'author__username': 'jacob'}).qs.count(), 1)
class F(FilterSet):
author__username = AllValuesFilter()
class Meta:
model = Article
fields = ['author__username']
self.assertEqual(F({'author__username': 'alex'}).qs.count(), 2)
def test_reverse_fk_relation_attribute(self):
alex = User.objects.create(username='alex')
jacob = User.objects.create(username='jacob')
date = now().date()
time = now().time()
Comment.objects.create(text='comment 1',
author=jacob, time=time, date=date)
Comment.objects.create(text='comment 2',
author=alex, time=time, date=date)
Comment.objects.create(text='comment 3',
author=jacob, time=time, date=date)
class F(FilterSet):
class Meta:
model = User
fields = ['comments__text']
qs = User.objects.all()
f = F({'comments__text': 'comment 2'}, queryset=qs)
self.assertQuerysetEqual(f.qs, ['alex'], lambda o: o.username)
class F(FilterSet):
comments__text = AllValuesFilter()
class Meta:
model = User
fields = ['comments__text']
f = F({'comments__text': 'comment 2'}, queryset=qs)
self.assertQuerysetEqual(f.qs, ['alex'], lambda o: o.username)
@unittest.skip('todo - need correct models')
def test_fk_relation_multiple_attributes(self):
pass
@unittest.expectedFailure
def test_reverse_fk_relation_multiple_attributes(self):
company = Company.objects.create(name='company')
Location.objects.create(
company=company, open_days="some", zip_code="90210")
Location.objects.create(
company=company, open_days="WEEKEND", zip_code="11111")
class F(FilterSet):
class Meta:
model = Company
fields = ('locations__zip_code', 'locations__open_days')
f = F({'locations__zip_code': '90210',
'locations__open_days': 'WEEKEND'})
self.assertEqual(f.qs.count(), 0)
class M2MRelationshipTests(TestCase):
def setUp(self):
alex = User.objects.create(username='alex', status=1)
User.objects.create(username='jacob', status=1)
aaron = User.objects.create(username='aaron', status=1)
b1 = Book.objects.create(title="Ender's Game", price='1.00',
average_rating=3.0)
b2 = Book.objects.create(title="Rainbow Six", price='2.00',
average_rating=4.0)
b3 = Book.objects.create(title="Snowcrash", price='1.00',
average_rating=4.0)
Book.objects.create(title="Stranger in a Strage Land", price='2.00',
average_rating=3.0)
alex.favorite_books = [b1, b2]
aaron.favorite_books = [b1, b3]
def test_m2m_relation(self):
class F(FilterSet):
class Meta:
model = User
fields = ['favorite_books']
qs = User.objects.all().order_by('username')
f = F({'favorite_books': ['1']}, queryset=qs)
self.assertQuerysetEqual(f.qs, ['aaron', 'alex'], lambda o: o.username)
f = F({'favorite_books': ['1', '3']}, queryset=qs)
self.assertQuerysetEqual(f.qs, ['aaron', 'alex'], lambda o: o.username)
f = F({'favorite_books': ['2']}, queryset=qs)
self.assertQuerysetEqual(f.qs, ['alex'], lambda o: o.username)
f = F({'favorite_books': ['4']}, queryset=qs)
self.assertQuerysetEqual(f.qs, [], lambda o: o.username)
def test_reverse_m2m_relation(self):
with self.assertRaises(AttributeError):
class F(FilterSet):
class Meta:
model = Book
fields = ['lovers']
# qs = User.objects.all()
# f = F({'lovers': [1]}, queryset=qs)
# self.assertQuerysetEqual(
# f.qs, ["Ender's Game", "Rainbow Six"], lambda o: o.title)
with self.assertRaises(AttributeError):
class F(FilterSet):
lovers = AllValuesFilter()
class Meta:
model = Book
fields = ['lovers']
# f = F({'lovers': 1}, queryset=qs)
# self.assertQuerysetEqual(
# f.qs, ["Ender's Game", "Rainbow Six"], lambda o: o.title)
def test_m2m_relation_attribute(self):
class F(FilterSet):
class Meta:
model = User
fields = ['favorite_books__title']
qs = User.objects.all().order_by('username')
f = F({'favorite_books__title': "Ender's Game"}, queryset=qs)
self.assertQuerysetEqual(f.qs, ['aaron', 'alex'], lambda o: o.username)
f = F({'favorite_books__title': 'Rainbow Six'}, queryset=qs)
self.assertQuerysetEqual(f.qs, ['alex'], lambda o: o.username)
class F(FilterSet):
favorite_books__title = MultipleChoiceFilter()
class Meta:
model = User
fields = ['favorite_books__title']
f = F()
self.assertEqual(
len(f.filters['favorite_books__title'].field.choices), 0)
# f = F({'favorite_books__title': ['1', '3']},
# queryset=qs)
# self.assertQuerysetEqual(
# f.qs, ['aaron', 'alex'], lambda o: o.username)
class F(FilterSet):
favorite_books__title = AllValuesFilter()
class Meta:
model = User
fields = ['favorite_books__title']
f = F({'favorite_books__title': "Snowcrash"}, queryset=qs)
self.assertQuerysetEqual(f.qs, ['aaron'], lambda o: o.username)
def test_reverse_m2m_relation_attribute(self):
class F(FilterSet):
class Meta:
model = Book
fields = ['lovers__username']
qs = Book.objects.all().order_by('title')
f = F({'lovers__username': "alex"}, queryset=qs)
self.assertQuerysetEqual(
f.qs, ["Ender's Game", "Rainbow Six"], lambda o: o.title)
f = F({'lovers__username': 'jacob'}, queryset=qs)
self.assertQuerysetEqual(f.qs, [], lambda o: o.title)
class F(FilterSet):
lovers__username = MultipleChoiceFilter()
class Meta:
model = Book
fields = ['lovers__username']
f = F()
self.assertEqual(
len(f.filters['lovers__username'].field.choices), 0)
# f = F({'lovers__username': ['1', '3']},
# queryset=qs)
# self.assertQuerysetEqual(
# f.qs, ["Ender's Game", "Rainbow Six"], lambda o: o.title)
class F(FilterSet):
lovers__username = AllValuesFilter()
class Meta:
model = Book
fields = ['lovers__username']
f = F({'lovers__username': "alex"}, queryset=qs)
self.assertQuerysetEqual(
f.qs, ["Ender's Game", "Rainbow Six"], lambda o: o.title)
@unittest.expectedFailure
def test_m2m_relation_multiple_attributes(self):
class F(FilterSet):
class Meta:
model = User
fields = ['favorite_books__price',
'favorite_books__average_rating']
qs = User.objects.all().order_by('username')
f = F({'favorite_books__price': "1.00",
'favorite_books__average_rating': 4.0},
queryset=qs)
self.assertQuerysetEqual(f.qs, ['aaron'], lambda o: o.username)
f = F({'favorite_books__price': "3.00",
'favorite_books__average_rating': 4.0},
queryset=qs)
self.assertQuerysetEqual(f.qs, [], lambda o: o.username)
@unittest.expectedFailure
def test_reverse_m2m_relation_multiple_attributes(self):
class F(FilterSet):
class Meta:
model = Book
fields = ['lovers__status', 'lovers__username']
qs = Book.objects.all().order_by('title')
f = F({'lovers__status': 1, 'lovers__username': "alex"}, queryset=qs)
self.assertQuerysetEqual(
f.qs, ["Ender's Game", "Rainbow Six"], lambda o: o.title)
f = F({'lovers__status': 1, 'lovers__username': 'jacob'}, queryset=qs)
self.assertQuerysetEqual(f.qs, [], lambda o: o.title)
@unittest.skip('todo')
def test_fk_relation_on_m2m_relation(self):
pass
@unittest.skip('todo')
def test_fk_relation_attribute_on_m2m_relation(self):
pass
class SelfReferentialRelationshipTests(TestCase):
@unittest.skip('todo')
def test_self_referential_m2m_relation(self):
pass
@unittest.skip('todo')
def test_reverse_self_referential_m2m_relation(self):
pass
class MiscFilterSetTests(TestCase):
def setUp(self):
User.objects.create(username='alex', status=1)
User.objects.create(username='jacob', status=2)
User.objects.create(username='aaron', status=2)
User.objects.create(username='carl', status=0)
def test_filtering_with_declared_filters(self):
class F(FilterSet):
account = CharFilter(name='username')
class Meta:
model = User
fields = ['account']
qs = mock.MagicMock()
f = F({'account': 'jdoe'}, queryset=qs)
result = f.qs
self.assertNotEqual(qs, result)
qs.all.return_value.filter.assert_called_with(username__exact='jdoe')
def test_filtering_with_multiple_filters(self):
class F(FilterSet):
class Meta:
model = User
fields = ['status', 'username']
qs = User.objects.all()
f = F({'username': 'alex', 'status': '1'}, queryset=qs)
self.assertQuerysetEqual(f.qs, ['alex'], lambda o: o.username)
f = F({'username': 'alex', 'status': '2'}, queryset=qs)
self.assertQuerysetEqual(f.qs, [], lambda o: o.pk)
def test_filter_with_action(self):
class F(FilterSet):
username = CharFilter(action=lambda qs, value: (
qs.filter(**{'username__startswith': value})))
class Meta:
model = User
fields = ['username']
f = F({'username': 'a'}, queryset=User.objects.all())
self.assertQuerysetEqual(
f.qs, ['alex', 'aaron'], lambda o: o.username, False)
def test_filter_with_initial(self):
class F(FilterSet):
status = ChoiceFilter(choices=STATUS_CHOICES, initial=1)
class Meta:
model = User
fields = ['status']
qs = User.objects.all()
f = F(queryset=qs)
self.assertQuerysetEqual(f.qs, ['alex'], lambda o: o.username)
f = F({'status': 0}, queryset=qs)
self.assertQuerysetEqual(f.qs, ['carl'], lambda o: o.username)
def test_qs_count(self):
class F(FilterSet):
class Meta:
model = User
fields = ['status']
qs = User.objects.all()
f = F(queryset=qs)
self.assertEqual(len(f.qs), 4)
self.assertEqual(f.count(), 4)
f = F({'status': '0'}, queryset=qs)
self.assertEqual(len(f.qs), 1)
self.assertEqual(f.count(), 1)
f = F({'status': '1'}, queryset=qs)
self.assertEqual(len(f.qs), 1)
self.assertEqual(f.count(), 1)
f = F({'status': '2'}, queryset=qs)
self.assertEqual(len(f.qs), 2)
self.assertEqual(f.count(), 2)

View File

@ -2,37 +2,26 @@ from __future__ import absolute_import
from __future__ import unicode_literals
import mock
import datetime
from django.db import models
from django.utils import unittest
from django.test import TestCase
from django.utils import six
from django.utils.timezone import now
from django.utils import timezone
from django_filters.filterset import FilterSet
from django_filters.filterset import FILTER_FOR_DBFIELD_DEFAULTS
from django_filters.filters import AllValuesFilter
from django_filters.filterset import get_model_field
from django_filters.filters import CharFilter
from django_filters.filters import ChoiceFilter
from django_filters.filters import DateRangeFilter
# from django_filters.filters import DateTimeFilter
from django_filters.filters import MultipleChoiceFilter
from django_filters.filters import NumberFilter
from django_filters.filters import RangeFilter
# from django_filters.widgets import LinkWidget
from django_filters.filters import ModelMultipleChoiceFilter
from .models import User
from .models import Comment
from .models import AdminUser
from .models import Book
from .models import Restaurant
from .models import Article
from .models import NetworkSetting
from .models import SubnetMaskField
from .models import Company
from .models import Location
from .models import STATUS_CHOICES
from .models import Account
from .models import BankAccount
class HelperMethodsTests(TestCase):
@ -41,9 +30,9 @@ class HelperMethodsTests(TestCase):
def test_get_declared_filters(self):
pass
@unittest.skip('todo')
def test_get_model_field(self):
pass
result = get_model_field(User, 'unknown__name')
self.assertIsNone(result)
@unittest.skip('todo')
def test_filters_for_model(self):
@ -103,21 +92,32 @@ class DbFieldDefaultFiltersTests(TestCase):
class FilterSetFilterForFieldTests(TestCase):
@unittest.skip('todo')
def test_filter_found_for_field(self):
pass
f = User._meta.get_field('username')
result = FilterSet.filter_for_field(f, 'username')
self.assertIsInstance(result, CharFilter)
self.assertEqual(result.name, 'username')
@unittest.skip('todo')
def test_filter_not_found_for_field(self):
pass
f = User._meta.get_field('id')
result = FilterSet.filter_for_field(f, 'id')
self.assertIsNone(result)
@unittest.skip('todo')
def test_filter_for_field_with_extras(self):
pass
f = User._meta.get_field('favorite_books')
result = FilterSet.filter_for_field(f, 'favorite_books')
self.assertIsInstance(result, ModelMultipleChoiceFilter)
self.assertEqual(result.name, 'favorite_books')
self.assertTrue('queryset' in result.extra)
self.assertIsNotNone(result.extra['queryset'])
@unittest.skip('todo')
def test_filter_for_field_with_choices(self):
pass
f = User._meta.get_field('status')
result = FilterSet.filter_for_field(f, 'status')
self.assertIsInstance(result, ChoiceFilter)
self.assertEqual(result.name, 'status')
self.assertTrue('choices' in result.extra)
self.assertIsNotNone(result.extra['choices'])
def test_filter_for_field_that_is_subclassed(self):
f = User._meta.get_field('first_name')
@ -267,829 +267,72 @@ class FilterSetClassCreationTests(TestCase):
self.assertEqual(list(F.base_filters.keys()), ['ip', 'mask'])
class CharFilterTests(TestCase):
def test_filtering(self):
b1 = Book.objects.create(
title="Ender's Game", price='1.00', average_rating=3.0)
b2 = Book.objects.create(
title="Rainbow Six", price='1.00', average_rating=3.0)
b3 = Book.objects.create(
title="Snowcrash", price='1.00', average_rating=3.0)
class F(FilterSet):
class Meta:
model = Book
fields = ['title']
qs = Book.objects.all()
f = F(queryset=qs)
self.assertQuerysetEqual(f.qs, [b1.pk, b2.pk, b3.pk],
lambda o: o.pk, ordered=False)
f = F({'title': 'Snowcrash'}, queryset=qs)
self.assertQuerysetEqual(f.qs, [b3.pk], lambda o: o.pk)
class BooleanFilterTests(TestCase):
def test_filtering(self):
User.objects.create(username='alex', is_active=False)
User.objects.create(username='jacob', is_active=True)
User.objects.create(username='aaron', is_active=False)
def test_filterset_for_proxy_model(self):
class F(FilterSet):
class Meta:
model = User
fields = ['is_active']
qs = User.objects.all()
# '2' and '3' are how the field expects the data from the browser
f = F({'is_active': '2'}, queryset=qs)
self.assertQuerysetEqual(f.qs, ['jacob'], lambda o: o.username, False)
f = F({'is_active': '3'}, queryset=qs)
self.assertQuerysetEqual(f.qs,
['alex', 'aaron'],
lambda o: o.username, False)
f = F({'is_active': '1'}, queryset=qs)
self.assertQuerysetEqual(f.qs,
['alex', 'aaron', 'jacob'],
lambda o: o.username, False)
class ChoiceFilterTests(TestCase):
def test_filtering(self):
User.objects.create(username='alex', status=1)
User.objects.create(username='jacob', status=2)
User.objects.create(username='aaron', status=2)
User.objects.create(username='carl', status=0)
class F(FilterSet):
class ProxyF(FilterSet):
class Meta:
model = User
fields = ['status']
model = AdminUser
f = F()
self.assertQuerysetEqual(f.qs,
['aaron', 'alex', 'jacob', 'carl'],
lambda o: o.username, False)
f = F({'status': '1'})
self.assertQuerysetEqual(f.qs, ['alex'], lambda o: o.username, False)
f = F({'status': '2'})
self.assertQuerysetEqual(f.qs, ['jacob', 'aaron'],
lambda o: o.username, False)
f = F({'status': '0'})
self.assertQuerysetEqual(f.qs, ['carl'], lambda o: o.username, False)
class MultipleChoiceFilterTests(TestCase):
def test_filtering(self):
User.objects.create(username='alex', status=1)
User.objects.create(username='jacob', status=2)
User.objects.create(username='aaron', status=2)
User.objects.create(username='carl', status=0)
class F(FilterSet):
status = MultipleChoiceFilter(choices=STATUS_CHOICES)
class Meta:
model = User
fields = ['status']
qs = User.objects.all().order_by('username')
f = F(queryset=qs)
self.assertQuerysetEqual(
f.qs, ['aaron', 'jacob', 'alex', 'carl'],
lambda o: o.username, False)
f = F({'status': ['0']}, queryset=qs)
self.assertQuerysetEqual(
f.qs, ['carl'], lambda o: o.username)
f = F({'status': ['0', '1']}, queryset=qs)
self.assertQuerysetEqual(
f.qs, ['alex', 'carl'], lambda o: o.username)
f = F({'status': ['0', '1', '2']}, queryset=qs)
self.assertQuerysetEqual(
f.qs, ['aaron', 'alex', 'carl', 'jacob'], lambda o: o.username)
class DateFilterTests(TestCase):
def test_filtering(self):
today = now().date()
timestamp = now().time().replace(microsecond=0)
last_week = today - datetime.timedelta(days=7)
check_date = six.text_type(last_week)
u = User.objects.create(username='alex')
Comment.objects.create(author=u, time=timestamp, date=today)
Comment.objects.create(author=u, time=timestamp, date=last_week)
Comment.objects.create(author=u, time=timestamp, date=today)
Comment.objects.create(author=u, time=timestamp, date=last_week)
class F(FilterSet):
class Meta:
model = Comment
fields = ['date']
f = F({'date': check_date}, queryset=Comment.objects.all())
self.assertEqual(len(f.qs), 2)
self.assertQuerysetEqual(f.qs, [2, 4], lambda o: o.pk)
class TimeFilterTests(TestCase):
def test_filtering(self):
today = now().date()
now_time = now().time().replace(microsecond=0)
ten_min_ago = (now() - datetime.timedelta(minutes=10))
fixed_time = ten_min_ago.time().replace(microsecond=0)
check_time = six.text_type(fixed_time)
u = User.objects.create(username='alex')
Comment.objects.create(author=u, time=now_time, date=today)
Comment.objects.create(author=u, time=fixed_time, date=today)
Comment.objects.create(author=u, time=now_time, date=today)
Comment.objects.create(author=u, time=fixed_time, date=today)
class F(FilterSet):
class Meta:
model = Comment
fields = ['time']
f = F({'time': check_time}, queryset=Comment.objects.all())
self.assertEqual(len(f.qs), 2)
self.assertQuerysetEqual(f.qs, [2, 4], lambda o: o.pk)
class DateTimeFilterTests(TestCase):
def test_filtering(self):
now_dt = now()
ten_min_ago = now_dt - datetime.timedelta(minutes=10)
one_day_ago = now_dt - datetime.timedelta(days=1)
u = User.objects.create(username='alex')
Article.objects.create(author=u, published=now_dt)
Article.objects.create(author=u, published=ten_min_ago)
Article.objects.create(author=u, published=one_day_ago)
tz = timezone.get_current_timezone()
# make naive, like a browser would send
local_ten_min_ago = timezone.make_naive(ten_min_ago, tz)
check_dt = six.text_type(local_ten_min_ago)
class F(FilterSet):
class Meta:
model = Article
fields = ['published']
qs = Article.objects.all()
f = F({'published': ten_min_ago}, queryset=qs)
self.assertEqual(len(f.qs), 1)
self.assertQuerysetEqual(f.qs, [2], lambda o: o.pk)
# this is how it would come through a browser
f = F({'published': check_dt}, queryset=qs)
self.assertEqual(len(f.qs), 1,
"%s isn't matching %s when cleaned" % (check_dt, ten_min_ago))
self.assertQuerysetEqual(f.qs, [2], lambda o: o.pk)
class ModelChoiceFilterTests(TestCase):
def test_filtering(self):
alex = User.objects.create(username='alex')
jacob = User.objects.create(username='jacob')
date = now().date()
time = now().time()
Comment.objects.create(author=jacob, time=time, date=date)
Comment.objects.create(author=alex, time=time, date=date)
Comment.objects.create(author=jacob, time=time, date=date)
class F(FilterSet):
class Meta:
model = Comment
fields = ['author']
qs = Comment.objects.all()
f = F({'author': jacob.pk}, queryset=qs)
self.assertQuerysetEqual(f.qs, [1, 3], lambda o: o.pk)
class ModelMultipleChoiceFilterTests(TestCase):
def setUp(self):
alex = User.objects.create(username='alex')
User.objects.create(username='jacob')
aaron = User.objects.create(username='aaron')
b1 = Book.objects.create(title="Ender's Game", price='1.00',
average_rating=3.0)
b2 = Book.objects.create(title="Rainbow Six", price='1.00',
average_rating=3.0)
b3 = Book.objects.create(title="Snowcrash", price='1.00',
average_rating=3.0)
Book.objects.create(title="Stranger in a Strage Land", price='1.00',
average_rating=3.0)
alex.favorite_books = [b1, b2]
aaron.favorite_books = [b1, b3]
def test_filtering(self):
class F(FilterSet):
class Meta:
model = User
fields = ['favorite_books']
qs = User.objects.all().order_by('username')
f = F({'favorite_books': ['1']}, queryset=qs)
self.assertQuerysetEqual(f.qs, ['aaron', 'alex'], lambda o: o.username)
f = F({'favorite_books': ['1', '3']}, queryset=qs)
self.assertQuerysetEqual(f.qs, ['aaron', 'alex'], lambda o: o.username)
f = F({'favorite_books': ['2']}, queryset=qs)
self.assertQuerysetEqual(f.qs, ['alex'], lambda o: o.username)
f = F({'favorite_books': ['4']}, queryset=qs)
self.assertQuerysetEqual(f.qs, [], lambda o: o.username)
class NumberFilterTests(TestCase):
def setUp(self):
Book.objects.create(title="Ender's Game", price='10.0',
average_rating=4.7999999999999998)
Book.objects.create(title="Rainbow Six", price='15.0',
average_rating=4.5999999999999996)
Book.objects.create(title="Snowcrash", price='20.0',
average_rating=4.2999999999999998)
def test_filtering(self):
class F(FilterSet):
class Meta:
model = Book
fields = ['price']
f = F({'price': 10}, queryset=Book.objects.all())
self.assertQuerysetEqual(f.qs, ['Ender\'s Game'], lambda o: o.title)
def test_filtering_with_single_lookup_type(self):
class F(FilterSet):
price = NumberFilter(lookup_type='lt')
class Meta:
model = Book
fields = ['price']
f = F({'price': 16}, queryset=Book.objects.all().order_by('title'))
self.assertQuerysetEqual(
f.qs, ['Ender\'s Game', 'Rainbow Six'], lambda o: o.title)
def test_filtering_with_multiple_lookup_types(self):
class F(FilterSet):
price = NumberFilter(lookup_type=['lt', 'gt'])
class Meta:
model = Book
fields = ['price']
qs = Book.objects.all()
f = F({'price_0': '15', 'price_1': 'lt'}, queryset=qs)
self.assertQuerysetEqual(f.qs, ['Ender\'s Game'], lambda o: o.title)
f = F({'price_0': '15', 'price_1': 'lt'})
self.assertQuerysetEqual(f.qs, ['Ender\'s Game'], lambda o: o.title)
f = F({'price_0': '', 'price_1': 'lt'})
self.assertQuerysetEqual(f.qs,
['Ender\'s Game', 'Rainbow Six', 'Snowcrash'],
lambda o: o.title, ordered=False)
class F(FilterSet):
price = NumberFilter(lookup_type=['lt', 'gt', 'exact'])
class Meta:
model = Book
fields = ['price']
f = F({'price_0': '15'})
self.assertQuerysetEqual(f.qs, ['Rainbow Six'], lambda o: o.title)
class RangeFilterTests(TestCase):
def setUp(self):
Book.objects.create(title="Ender's Game", price='10.0',
average_rating=4.7999999999999998)
Book.objects.create(title="Rainbow Six", price='15.0',
average_rating=4.5999999999999996)
Book.objects.create(title="Snowcrash", price='20.0',
average_rating=4.2999999999999998)
def test_filtering(self):
class F(FilterSet):
price = RangeFilter()
class Meta:
model = Book
fields = ['price']
qs = Book.objects.all().order_by('title')
f = F(queryset=qs)
self.assertQuerysetEqual(f.qs,
['Ender\'s Game', 'Rainbow Six', 'Snowcrash'],
lambda o: o.title)
f = F({'price_0': '5', 'price_1': '15'}, queryset=qs)
self.assertQuerysetEqual(f.qs,
['Ender\'s Game', 'Rainbow Six'],
lambda o: o.title)
@unittest.skip('date-range is funky')
class DateRangeFilterTests(TestCase):
def setUp(self):
today = now().date()
five_days_ago = today - datetime.timedelta(days=5)
two_weeks_ago = today - datetime.timedelta(days=14)
two_months_ago = today - datetime.timedelta(days=62)
two_years_ago = today - datetime.timedelta(days=800)
alex = User.objects.create(username='alex')
time = now().time()
Comment.objects.create(date=two_weeks_ago, author=alex, time=time)
Comment.objects.create(date=two_years_ago, author=alex, time=time)
Comment.objects.create(date=five_days_ago, author=alex, time=time)
Comment.objects.create(date=today, author=alex, time=time)
Comment.objects.create(date=two_months_ago, author=alex, time=time)
def test_filtering_for_year(self):
class F(FilterSet):
date = DateRangeFilter()
class Meta:
model = Comment
fields = ['date']
f = F({'date': '4'}) # this year
self.assertQuerysetEqual(f.qs, [1, 3, 4, 5], lambda o: o.pk, False)
def test_filtering_for_month(self):
class F(FilterSet):
date = DateRangeFilter()
class Meta:
model = Comment
fields = ['date']
f = F({'date': '3'}) # this month
self.assertQuerysetEqual(f.qs, [1, 3, 4], lambda o: o.pk, False)
self.assertEqual(list(F.base_filters), list(ProxyF.base_filters))
@unittest.expectedFailure
def test_filtering_for_week(self):
def test_filterset_for_mti_model(self):
class F(FilterSet):
date = DateRangeFilter()
class Meta:
model = Comment
fields = ['date']
f = F({'date': '2'}) # this week
self.assertQuerysetEqual(f.qs, [3, 4], lambda o: o.pk, False)
def test_filtering_for_today(self):
class F(FilterSet):
date = DateRangeFilter()
model = Account
class FtiF(FilterSet):
class Meta:
model = Comment
fields = ['date']
model = BankAccount
f = F({'date': '1'}) # today
self.assertQuerysetEqual(f.qs, [4], lambda o: o.pk, False)
# it will be difficult to test for TZ related issues, where "today" means
# different things to both user and server.
# fails due to 'account_ptr' getting picked up
self.assertEqual(
list(F.base_filters) + ['amount_saved'],
list(FtiF.base_filters))
class AllValuesFilterTests(TestCase):
def test_filtering(self):
User.objects.create(username='alex')
User.objects.create(username='jacob')
User.objects.create(username='aaron')
class FilterSetInstantiationTests(TestCase):
def test_creating_instance(self):
class F(FilterSet):
username = AllValuesFilter()
class Meta:
model = User
fields = ['username']
self.assertEqual(list(F().qs), list(User.objects.all()))
self.assertEqual(list(F({'username': 'alex'})),
[User.objects.get(username='alex')])
self.assertEqual(list(F({'username': 'jose'})),
list(User.objects.all()))
class RelatedObjectTests(TestCase):
@unittest.skip('todo')
def test_o2o_relation(self):
pass
@unittest.skip('todo')
def test_reverse_o2o_relation(self):
pass
@unittest.skip('todo')
def test_o2o_relation_attribute(self):
pass
@unittest.skip('todo')
def test_reverse_o2o_relation_attribute(self):
pass
@unittest.skip('todo')
def test_fk_relation(self):
pass
def test_reverse_fk_relation(self):
alex = User.objects.create(username='alex')
jacob = User.objects.create(username='jacob')
date = now().date()
time = now().time()
Comment.objects.create(text='comment 1',
author=jacob, time=time, date=date)
Comment.objects.create(text='comment 2',
author=alex, time=time, date=date)
Comment.objects.create(text='comment 3',
author=jacob, time=time, date=date)
with self.assertRaises(AttributeError):
class F(FilterSet):
class Meta:
model = User
fields = ['comments']
# qs = User.objects.all()
# f = F({'comment': 2}, queryset=qs)
# self.assertQuerysetEqual(f.qs, ['alex'], lambda o: o.username)
with self.assertRaises(AttributeError):
class F(FilterSet):
comment = AllValuesFilter()
class Meta:
model = User
fields = ['comments']
# f = F({'comments': 2}, queryset=qs)
# self.assertQuerysetEqual(f.qs, ['alex'], lambda o: o.username)
def test_fk_relation_attribute(self):
now_dt = now()
alex = User.objects.create(username='alex')
jacob = User.objects.create(username='jacob')
User.objects.create(username='aaron')
Article.objects.create(author=alex, published=now_dt)
Article.objects.create(author=jacob, published=now_dt)
Article.objects.create(author=alex, published=now_dt)
class F(FilterSet):
class Meta:
model = Article
fields = ['author__username']
self.assertEqual(list(F.base_filters), ['author__username'])
self.assertEqual(F({'author__username': 'alex'}).qs.count(), 2)
self.assertEqual(F({'author__username': 'jacob'}).qs.count(), 1)
class F(FilterSet):
author__username = AllValuesFilter()
class Meta:
model = Article
fields = ['author__username']
self.assertEqual(F({'author__username': 'alex'}).qs.count(), 2)
def test_reverse_fk_relation_attribute(self):
alex = User.objects.create(username='alex')
jacob = User.objects.create(username='jacob')
date = now().date()
time = now().time()
Comment.objects.create(text='comment 1',
author=jacob, time=time, date=date)
Comment.objects.create(text='comment 2',
author=alex, time=time, date=date)
Comment.objects.create(text='comment 3',
author=jacob, time=time, date=date)
class F(FilterSet):
class Meta:
model = User
fields = ['comments__text']
qs = User.objects.all()
f = F({'comments__text': 'comment 2'}, queryset=qs)
self.assertQuerysetEqual(f.qs, ['alex'], lambda o: o.username)
class F(FilterSet):
comments__text = AllValuesFilter()
class Meta:
model = User
fields = ['comments__text']
f = F({'comments__text': 'comment 2'}, queryset=qs)
self.assertQuerysetEqual(f.qs, ['alex'], lambda o: o.username)
@unittest.skip('todo')
def test_m2m_relation(self):
pass
def test_reverse_m2m_relation(self):
alex = User.objects.create(username='alex')
User.objects.create(username='jacob')
aaron = User.objects.create(username='aaron')
b1 = Book.objects.create(title="Ender's Game", price='1.00',
average_rating=3.0)
b2 = Book.objects.create(title="Rainbow Six", price='1.00',
average_rating=3.0)
b3 = Book.objects.create(title="Snowcrash", price='1.00',
average_rating=3.0)
Book.objects.create(title="Stranger in a Strage Land", price='1.00',
average_rating=3.0)
alex.favorite_books = [b1, b2]
aaron.favorite_books = [b1, b3]
with self.assertRaises(AttributeError):
class F(FilterSet):
class Meta:
model = Book
fields = ['lovers']
# qs = User.objects.all()
# f = F({'lovers': [1]}, queryset=qs)
# self.assertQuerysetEqual(
# f.qs, ["Ender's Game", "Rainbow Six"], lambda o: o.title)
with self.assertRaises(AttributeError):
class F(FilterSet):
lovers = AllValuesFilter()
class Meta:
model = Book
fields = ['lovers']
# f = F({'lovers': 1}, queryset=qs)
# self.assertQuerysetEqual(
# f.qs, ["Ender's Game", "Rainbow Six"], lambda o: o.title)
def test_m2m_relation_attribute(self):
alex = User.objects.create(username='alex')
User.objects.create(username='jacob')
aaron = User.objects.create(username='aaron')
b1 = Book.objects.create(title="Ender's Game", price='1.00',
average_rating=3.0)
b2 = Book.objects.create(title="Rainbow Six", price='1.00',
average_rating=3.0)
b3 = Book.objects.create(title="Snowcrash", price='1.00',
average_rating=3.0)
Book.objects.create(title="Stranger in a Strage Land", price='1.00',
average_rating=3.0)
alex.favorite_books = [b1, b2]
aaron.favorite_books = [b1, b3]
class F(FilterSet):
class Meta:
model = User
fields = ['favorite_books__title']
qs = User.objects.all().order_by('username')
f = F({'favorite_books__title': "Ender's Game"}, queryset=qs)
self.assertQuerysetEqual(f.qs, ['aaron', 'alex'], lambda o: o.username)
f = F({'favorite_books__title': 'Rainbow Six'}, queryset=qs)
self.assertQuerysetEqual(f.qs, ['alex'], lambda o: o.username)
class F(FilterSet):
favorite_books__title = MultipleChoiceFilter()
class Meta:
model = User
fields = ['favorite_books__title']
f = F()
self.assertEqual(
len(f.filters['favorite_books__title'].field.choices), 0)
# f = F({'favorite_books__title': ['1', '3']},
# queryset=qs)
# self.assertQuerysetEqual(
# f.qs, ['aaron', 'alex'], lambda o: o.username)
self.assertFalse(f.is_bound)
self.assertIsNotNone(f.queryset)
self.assertEqual(len(f.filters), len(F.base_filters))
for name, filter_ in f.filters.items():
self.assertEqual(
filter_.model,
User,
"%s does not have model set correctly" % name)
def test_creating_bound_instance(self):
class F(FilterSet):
favorite_books__title = AllValuesFilter()
class Meta:
model = User
fields = ['favorite_books__title']
f = F({'favorite_books__title': "Snowcrash"}, queryset=qs)
self.assertQuerysetEqual(f.qs, ['aaron'], lambda o: o.username)
def test_reverse_m2m_relation_attribute(self):
alex = User.objects.create(username='alex')
User.objects.create(username='jacob')
aaron = User.objects.create(username='aaron')
b1 = Book.objects.create(title="Ender's Game", price='1.00',
average_rating=3.0)
b2 = Book.objects.create(title="Rainbow Six", price='1.00',
average_rating=3.0)
b3 = Book.objects.create(title="Snowcrash", price='1.00',
average_rating=3.0)
Book.objects.create(title="Stranger in a Strage Land", price='1.00',
average_rating=3.0)
alex.favorite_books = [b1, b2]
aaron.favorite_books = [b1, b3]
class F(FilterSet):
class Meta:
model = Book
fields = ['lovers__username']
qs = Book.objects.all().order_by('title')
f = F({'lovers__username': "alex"}, queryset=qs)
self.assertQuerysetEqual(
f.qs, ["Ender's Game", "Rainbow Six"], lambda o: o.title)
f = F({'lovers__username': 'jacob'}, queryset=qs)
self.assertQuerysetEqual(f.qs, [], lambda o: o.title)
class F(FilterSet):
lovers__username = MultipleChoiceFilter()
class Meta:
model = Book
fields = ['lovers__username']
f = F()
self.assertEqual(
len(f.filters['lovers__username'].field.choices), 0)
# f = F({'lovers__username': ['1', '3']},
# queryset=qs)
# self.assertQuerysetEqual(
# f.qs, ["Ender's Game", "Rainbow Six"], lambda o: o.title)
class F(FilterSet):
lovers__username = AllValuesFilter()
class Meta:
model = Book
fields = ['lovers__username']
f = F({'lovers__username': "alex"}, queryset=qs)
self.assertQuerysetEqual(
f.qs, ["Ender's Game", "Rainbow Six"], lambda o: o.title)
@unittest.skip('todo')
def test_fk_relation_on_m2m_relation(self):
pass
@unittest.skip('todo')
def test_fk_relation_attribute_on_m2m_relation(self):
pass
class ProblematicBehaviorTests(TestCase):
def setUp(self):
company = Company.objects.create(name='company')
Location.objects.create(
company=company, open_days="some", zip_code="90210")
Location.objects.create(
company=company, open_days="WEEKEND", zip_code="11111")
@unittest.expectedFailure
def test_related_attributes_filter_differently(self):
class F(FilterSet):
class Meta:
model = Company
fields = ('locations__zip_code', 'locations__open_days')
f = F({'locations__zip_code': '90210',
'locations__open_days': 'WEEKEND'})
self.assertEqual(f.qs.count(), 0)
class FilterSetTests(TestCase):
def test_filtering_with_declared_filters(self):
class F(FilterSet):
account = CharFilter(name='username')
class Meta:
model = User
fields = ['account']
qs = mock.MagicMock()
f = F({'account': 'jdoe'}, queryset=qs)
result = f.qs
self.assertNotEqual(qs, result)
qs.all.return_value.filter.assert_called_with(username__exact='jdoe')
def test_filtering_with_multiple_filters(self):
User.objects.create(username='alex', status=1)
User.objects.create(username='jacob', status=2)
User.objects.create(username='aaron', status=2)
User.objects.create(username='carl', status=0)
class F(FilterSet):
class Meta:
model = User
fields = ['status', 'username']
qs = User.objects.all()
f = F({'username': 'alex', 'status': '1'}, queryset=qs)
self.assertQuerysetEqual(f.qs, ['alex'], lambda o: o.username)
f = F({'username': 'alex', 'status': '2'}, queryset=qs)
self.assertQuerysetEqual(f.qs, [], lambda o: o.pk)
def test_filter_with_action(self):
User.objects.create(username='alex')
User.objects.create(username='jacob')
User.objects.create(username='aaron')
class F(FilterSet):
username = CharFilter(action=lambda qs, value: (
qs.filter(**{'username__startswith': value})))
class Meta:
model = User
fields = ['username']
f = F({'username': 'a'}, queryset=User.objects.all())
self.assertQuerysetEqual(
f.qs, ['alex', 'aaron'], lambda o: o.username, False)
def test_filter_with_initial(self):
User.objects.create(username='alex', status=1)
User.objects.create(username='jacob', status=2)
User.objects.create(username='aaron', status=2)
User.objects.create(username='carl', status=0)
class F(FilterSet):
status = ChoiceFilter(choices=STATUS_CHOICES, initial=1)
class Meta:
model = User
fields = ['status']
qs = User.objects.all()
f = F(queryset=qs)
self.assertQuerysetEqual(f.qs, ['alex'], lambda o: o.username)
f = F({'status': 0}, queryset=qs)
self.assertQuerysetEqual(f.qs, ['carl'], lambda o: o.username)
def test_qs_count(self):
User.objects.create(username='alex', status=1)
User.objects.create(username='jacob', status=2)
User.objects.create(username='aaron', status=2)
User.objects.create(username='carl', status=0)
f = F({'username': 'username'})
self.assertTrue(f.is_bound)
def test_creating_with_queryset(self):
class F(FilterSet):
class Meta:
model = User
fields = ['status']
fields = ['username']
qs = User.objects.all()
f = F(queryset=qs)
self.assertEqual(len(f.qs), 4)
self.assertEqual(f.count(), 4)
f = F({'status': '0'}, queryset=qs)
self.assertEqual(len(f.qs), 1)
self.assertEqual(f.count(), 1)
f = F({'status': '1'}, queryset=qs)
self.assertEqual(len(f.qs), 1)
self.assertEqual(f.count(), 1)
f = F({'status': '2'}, queryset=qs)
self.assertEqual(len(f.qs), 2)
self.assertEqual(f.count(), 2)
m = mock.Mock()
f = F(queryset=m)
self.assertEqual(f.queryset, m)
class FilterSetOrdering(TestCase):
class FilterSetOrderingTests(TestCase):
def setUp(self):
self.alex = User.objects.create(username='alex', status=1)
@ -1121,6 +364,17 @@ class FilterSetOrdering(TestCase):
self.assertQuerysetEqual(
f.qs, ['carl', 'alex', 'jacob', 'aaron'], lambda o: o.username)
def test_ordering_on_unknown_value_is_ignored(self):
class F(FilterSet):
class Meta:
model = User
fields = ['username', 'status']
order_by = ['status']
f = F({'o': 'username'}, queryset=self.qs)
self.assertQuerysetEqual(
f.qs, ['alex', 'jacob', 'aaron', 'carl'], lambda o: o.username)
def test_ordering_on_differnt_field(self):
class F(FilterSet):
class Meta:

View File

@ -2,26 +2,14 @@ from __future__ import absolute_import
from __future__ import unicode_literals
from django import forms
from django.utils import unittest
from django.test import TestCase
from django.utils import six
from django.utils.timezone import now
from django_filters.filterset import FilterSet
from django_filters.filters import AllValuesFilter
from django_filters.filters import CharFilter
from django_filters.filters import ChoiceFilter
from django_filters.filters import DateRangeFilter
from django_filters.filters import ModelChoiceFilter
from django_filters.filters import ModelMultipleChoiceFilter
from django_filters.filters import MultipleChoiceFilter
from django_filters.filters import RangeFilter
from django_filters.widgets import LinkWidget
from .models import User
from .models import Comment
from .models import Book
from .models import Article
from .models import STATUS_CHOICES
@ -42,17 +30,11 @@ class FilterSetFormTests(TestCase):
f = F().form
self.assertIsInstance(f, forms.Form)
self.assertHTMLEqual(six.text_type(f), """
<tr><th><label for="id_title">Title:</label></th>
<td>
<input type="text" name="title" id="id_title" />
</td>
</tr>""")
self.assertEqual(list(f.fields), ['title'])
def test_custom_form(self):
class MyForm(forms.Form):
def as_table(self):
return "lol string"
pass
class F(FilterSet):
class Meta:
@ -60,8 +42,7 @@ class FilterSetFormTests(TestCase):
form = MyForm
f = F().form
self.assertIsInstance(f, forms.Form)
self.assertEqual(six.text_type(f), 'lol string')
self.assertIsInstance(f, MyForm)
def test_form_prefix(self):
class F(FilterSet):
@ -74,12 +55,6 @@ class FilterSetFormTests(TestCase):
f = F(prefix='prefix').form
self.assertEqual(f.prefix, 'prefix')
self.assertHTMLEqual(six.text_type(f), """
<tr><th><label for="id_prefix-title">Title:</label></th>
<td>
<input type="text" name="prefix-title" id="id_prefix-title" />
</td>
</tr>""")
def test_form_fields(self):
class F(FilterSet):
@ -119,12 +94,8 @@ class FilterSetFormTests(TestCase):
fields = ('title',)
f = F().form
self.assertHTMLEqual(six.text_type(f), """
<tr><th><label for="id_title">Book title:</label></th>
<td>
<input type="text" name="title" id="id_title" />
</td>
</tr>""")
self.assertEqual(f.fields['title'].label, "Book title")
self.assertEqual(f['title'].label, 'Book title')
def test_form_field_with_manual_name(self):
class F(FilterSet):
@ -135,12 +106,8 @@ class FilterSetFormTests(TestCase):
fields = ('book_title',)
f = F().form
self.assertHTMLEqual(six.text_type(f), """
<tr><th><label for="id_book_title">Book title:</label></th>
<td>
<input type="text" name="book_title" id="id_book_title" />
</td>
</tr>""")
self.assertEqual(f.fields['book_title'].label, None)
self.assertEqual(f['book_title'].label, 'Book title')
def test_form_field_with_manual_name_and_label(self):
class F(FilterSet):
@ -151,12 +118,8 @@ class FilterSetFormTests(TestCase):
fields = ('f1',)
f = F().form
self.assertHTMLEqual(six.text_type(f), """
<tr><th><label for="id_f1">Book title:</label></th>
<td>
<input type="text" name="f1" id="id_f1" />
</td>
</tr>""")
self.assertEqual(f.fields['f1'].label, "Book title")
self.assertEqual(f['f1'].label, 'Book title')
def test_filter_with_initial(self):
class F(FilterSet):
@ -166,13 +129,28 @@ class FilterSetFormTests(TestCase):
model = User
fields = ['status']
f = F().form['status']
self.assertHTMLEqual(six.text_type(f), """
<select name="status" id="id_status">
<option value="0">Regular</option>
<option selected="selected" value="1">Manager</option>
<option value="2">Admin</option>
</select>""")
f = F().form
self.assertEqual(f.fields['status'].initial, 1)
def test_form_is_not_bound(self):
class F(FilterSet):
class Meta:
model = Book
fields = ('title',)
f = F().form
self.assertFalse(f.is_bound)
self.assertEqual(f.data, {})
def test_form_is_bound(self):
class F(FilterSet):
class Meta:
model = Book
fields = ('title',)
f = F({'title': 'Some book'}).form
self.assertTrue(f.is_bound)
self.assertEqual(f.data, {'title': 'Some book'})
def test_ordering(self):
class F(FilterSet):
@ -185,10 +163,6 @@ class FilterSetFormTests(TestCase):
self.assertEqual(len(f.fields), 3)
self.assertIn('o', f.fields)
self.assertEqual(f.fields['o'].choices, [('status', 'Status')])
self.assertHTMLEqual(six.text_type(f['o']), """
<select id="id_o" name="o">
<option value="status">Status</option>
</select>""")
def test_ordering_uses_all_fields(self):
class F(FilterSet):
@ -200,11 +174,6 @@ class FilterSetFormTests(TestCase):
f = F().form
self.assertEqual(f.fields['o'].choices,
[('username', 'Username'), ('status', 'Status')])
self.assertHTMLEqual(six.text_type(f['o']), """
<select id="id_o" name="o">
<option value="username">Username</option>
<option value="status">Status</option>
</select>""")
def test_ordering_uses_filter_label(self):
class F(FilterSet):
@ -231,11 +200,6 @@ class FilterSetFormTests(TestCase):
f = F().form
self.assertEqual(f.fields['o'].choices,
[('username', 'Account'), ('status', 'Status')])
self.assertHTMLEqual(six.text_type(f['o']), """
<select id="id_o" name="o">
<option value="username">Account</option>
<option value="status">Status</option>
</select>""")
def test_ordering_with_overridden_field_name(self):
"""
@ -254,10 +218,6 @@ class FilterSetFormTests(TestCase):
self.assertNotIn('o', f.fields)
self.assertIn('order', f.fields)
self.assertEqual(f.fields['order'].choices, [('status', 'Status')])
self.assertHTMLEqual(six.text_type(f['order']), """
<select id="id_order" name="order">
<option value="status">Status</option>
</select>""")
def test_ordering_with_overridden_field_name_and_using_all_fields(self):
class F(FilterSet):
@ -283,752 +243,4 @@ class FilterSetFormTests(TestCase):
f = F().form
self.assertEqual(
f.fields['o'].choices, [('status', 'Current status')])
self.assertHTMLEqual(six.text_type(f['o']), """
<select id="id_o" name="o">
<option value="status">Current status</option>
</select>""")
class CharFilterTests(TestCase):
def test_field_output(self):
class F(FilterSet):
class Meta:
model = Book
fields = ['title']
f = F().form['title']
self.assertHTMLEqual(six.text_type(f), '''
<input type="text" name="title" id="id_title" />''')
class BooleanFilterTests(TestCase):
def test_field_output(self):
class F(FilterSet):
class Meta:
model = User
fields = ['is_active']
f = F().form['is_active']
self.assertHTMLEqual(six.text_type(f), '''
<select name="is_active" id="id_is_active">
<option selected="selected" value="1">Unknown</option>
<option value="2">Yes</option>
<option value="3">No</option>
</select>''')
class ChoiceFilterTests(TestCase):
def test_field_output(self):
class F(FilterSet):
class Meta:
model = User
fields = ['status']
f = F().form['status']
self.assertHTMLEqual(six.text_type(f), """
<select name="status" id="id_status">
<option value="0">Regular</option>
<option value="1">Manager</option>
<option value="2">Admin</option>
</select>""")
def test_field_output_with_selection(self):
class F(FilterSet):
class Meta:
model = User
fields = ['status']
f = F({'status': '1'}).form['status']
self.assertHTMLEqual(six.text_type(f), """
<select name="status" id="id_status">
<option value="0">Regular</option>
<option selected="selected" value="1">Manager</option>
<option value="2">Admin</option>
</select>""")
def test_field_output_with_link_widget(self):
class F(FilterSet):
status = ChoiceFilter(widget=LinkWidget, choices=STATUS_CHOICES)
class Meta:
model = User
fields = ['status']
f = F().form['status']
self.assertHTMLEqual(six.text_type(f), """
<ul id="id_status">
<li><a href="?status=0">Regular</a></li>
<li><a href="?status=1">Manager</a></li>
<li><a href="?status=2">Admin</a></li>
</ul>""")
def test_field_output_with_link_widget_with_selection(self):
class F(FilterSet):
status = ChoiceFilter(widget=LinkWidget, choices=STATUS_CHOICES)
class Meta:
model = User
fields = ['status']
f = F({'status': '1'}).form['status']
self.assertHTMLEqual(six.text_type(f), """
<ul id="id_status">
<li><a href="?status=0">Regular</a></li>
<li><a class="selected" href="?status=1">Manager</a></li>
<li><a href="?status=2">Admin</a></li>
</ul>""")
class MultipleChoiceFilterTests(TestCase):
def test_field_output(self):
class F(FilterSet):
status = MultipleChoiceFilter(choices=STATUS_CHOICES)
class Meta:
model = User
fields = ['status']
f = F().form['status']
self.assertHTMLEqual(six.text_type(f), """
<select multiple="multiple" name="status" id="id_status">
<option value="0">Regular</option>
<option value="1">Manager</option>
<option value="2">Admin</option>
</select>""")
class DateFilterTests(TestCase):
def test_field_output(self):
class F(FilterSet):
class Meta:
model = Comment
fields = ['date']
f = F().form['date']
self.assertHTMLEqual(six.text_type(f), '''
<input type="text" name="date" id="id_date" />''')
class DateTimeFilterTests(TestCase):
def test_field_output(self):
class F(FilterSet):
class Meta:
model = Article
fields = ['published']
f = F().form['published']
self.assertHTMLEqual(six.text_type(f), '''
<input type="text" name="published" id="id_published" />''')
class TimeFilterTests(TestCase):
def test_field_output(self):
class F(FilterSet):
class Meta:
model = Comment
fields = ['time']
f = F().form['time']
self.assertHTMLEqual(six.text_type(f), '''
<input type="text" name="time" id="id_time" />''')
class ModelChoiceFilterTests(TestCase):
def test_field_output(self):
class F(FilterSet):
class Meta:
model = Comment
fields = ['author']
f = F().form['author']
self.assertHTMLEqual(six.text_type(f), """
<select name="author" id="id_author">
<option selected="selected" value="">---------</option>
</select>""")
def test_field_output_with_exising_objects(self):
User.objects.create(username='alex')
User.objects.create(username='jacob')
User.objects.create(username='aaron')
class F(FilterSet):
class Meta:
model = Comment
fields = ['author']
f = F().form['author']
self.assertHTMLEqual(six.text_type(f), """
<select name="author" id="id_author">
<option selected="selected" value="">---------</option>
<option value="1">alex</option>
<option value="2">jacob</option>
<option value="3">aaron</option>
</select>""")
def test_field_output_with_link_widget(self):
User.objects.create(username='alex')
User.objects.create(username='jacob')
User.objects.create(username='aaron')
class F(FilterSet):
author = ModelChoiceFilter(
widget=LinkWidget, queryset=User.objects.all())
class Meta:
model = Comment
fields = ['author']
f = F().form['author']
self.assertHTMLEqual(six.text_type(f), """
<ul id="id_author">
<li><a class="selected" href="?author=">All</a></li>
<li><a href="?author=1">alex</a></li>
<li><a href="?author=2">jacob</a></li>
<li><a href="?author=3">aaron</a></li>
</ul>""")
class ModelMultipleChoiceFilterTests(TestCase):
def test_field_output(self):
class F(FilterSet):
class Meta:
model = User
fields = ['favorite_books']
f = F().form['favorite_books']
self.assertHTMLEqual(six.text_type(f), """
<select multiple="multiple"
name="favorite_books"
id="id_favorite_books" />""")
def test_field_output_with_exising_objects(self):
Book.objects.create(
title="Ender's Game", price='1.00', average_rating=3.0)
Book.objects.create(
title="Rainbow Six", price='1.00', average_rating=3.0)
Book.objects.create(
title="Snowcrash", price='1.00', average_rating=3.0)
class F(FilterSet):
class Meta:
model = User
fields = ['favorite_books']
f = F().form['favorite_books']
self.assertHTMLEqual(six.text_type(f), """
<select multiple="multiple"
name="favorite_books" id="id_favorite_books">
<option value="1">Ender&39;s Game</option>
<option value="2">Rainbow Six</option>
<option value="3">Snowcrash</option>
</select>""")
def test_field_output_with_link_widget(self):
Book.objects.create(
title="Ender's Game", price='1.00', average_rating=3.0)
Book.objects.create(
title="Rainbow Six", price='1.00', average_rating=3.0)
Book.objects.create(
title="Snowcrash", price='1.00', average_rating=3.0)
class F(FilterSet):
favorite_books = ModelMultipleChoiceFilter(
widget=LinkWidget, queryset=Book.objects.all())
class Meta:
model = User
fields = ['favorite_books']
f = F().form['favorite_books']
self.assertHTMLEqual(six.text_type(f), """
<ul id="id_favorite_books">
<li><a href="?favorite_books=1">Ender's Game</a></li>
<li><a href="?favorite_books=2">Rainbow Six</a></li>
<li><a href="?favorite_books=3">Snowcrash</a></li>
</ul>""")
class NumberFilterTests(TestCase):
def test_field_output(self):
class F(FilterSet):
class Meta:
model = Book
fields = ['price']
f = F().form['price']
self.assertHTMLEqual(six.text_type(f), '''
<input type="text" name="price" id="id_price" />''')
class RangeFilterTests(TestCase):
def test_field_output(self):
class F(FilterSet):
price = RangeFilter()
class Meta:
model = Book
fields = ['price']
f = F().form['price']
self.assertHTMLEqual(six.text_type(f), '''
<input type="text" name="price_0" id="id_price_0" />
-
<input type="text" name="price_1" id="id_price_1" />''')
class DateRangeFilterTests(TestCase):
def test_field_output(self):
class F(FilterSet):
date = DateRangeFilter()
class Meta:
model = Comment
fields = ['date']
f = F().form['date']
self.assertHTMLEqual(six.text_type(f), """
<select name="date" id="id_date">
<option selected="selected" value="">Any Date</option>
<option value="1">Today</option>
<option value="2">Past 7 days</option>
<option value="3">This month</option>
<option value="4">This year</option>
</select>""")
def test_field_output_with_link_widget(self):
class F(FilterSet):
date = DateRangeFilter(widget=LinkWidget)
class Meta:
model = Comment
fields = ['date']
f = F()
self.assertHTMLEqual(six.text_type(f.form), """
<tr><th><label for="id_date">Date:</label></th>
<td>
<ul id="id_date">
<li><a class="selected" href="?date=">Any Date</a></li>
<li><a href="?date=1">Today</a></li>
<li><a href="?date=2">Past 7 days</a></li>
<li><a href="?date=3">This month</a></li>
<li><a href="?date=4">This year</a></li>
</ul>
</td>
</tr>""")
class AllValuesFilterTests(TestCase):
def setUp(self):
User.objects.create(username='alex')
User.objects.create(username='jacob')
User.objects.create(username='aaron')
def test_field_output(self):
class F(FilterSet):
username = AllValuesFilter()
class Meta:
model = User
fields = ['username']
f = F().form['username']
self.assertHTMLEqual(six.text_type(f), """
<select name="username" id="id_username">
<option value="aaron">aaron</option>
<option value="alex">alex</option>
<option value="jacob">jacob</option>
</select>""")
def test_field_output_with_link_widget(self):
class F(FilterSet):
username = AllValuesFilter(widget=LinkWidget)
class Meta:
model = User
fields = ['username']
f = F().form['username']
self.assertHTMLEqual(six.text_type(f), """
<ul id="id_username">
<li><a href="?username=aaron">aaron</a></li>
<li><a href="?username=alex">alex</a></li>
<li><a href="?username=jacob">jacob</a></li>
</ul>""")
class RelatedObjectTests(TestCase):
@unittest.skip('todo')
def test_o2o_relation(self):
pass
@unittest.skip('todo')
def test_reverse_o2o_relation(self):
pass
@unittest.skip('todo')
def test_o2o_relation_attribute(self):
pass
@unittest.skip('todo')
def test_reverse_o2o_relation_attribute(self):
pass
@unittest.skip('todo')
def test_fk_relation(self):
pass
@unittest.skip('todo')
def test_reverse_fk_relation(self):
pass
def test_fk_relation_attribute(self):
now_dt = now()
alex = User.objects.create(username='alex')
jacob = User.objects.create(username='jacob')
User.objects.create(username='aaron')
Article.objects.create(author=alex, published=now_dt)
Article.objects.create(author=jacob, published=now_dt)
Article.objects.create(author=alex, published=now_dt)
class F(FilterSet):
class Meta:
model = Article
fields = ['author__username']
f = F().form
self.assertHTMLEqual(six.text_type(f), """
<tr><th><label for="id_author__username">Username:</label></th>
<td>
<input type="text" name="author__username"
id="id_author__username" />
</td>
</tr>""")
class F(FilterSet):
author__username = AllValuesFilter()
class Meta:
model = Article
fields = ['author__username']
f = F().form
self.assertHTMLEqual(six.text_type(f), """
<tr>
<th>
<label for="id_author__username">Author username:</label>
</th>
<td>
<select name="author__username" id="id_author__username">
<option value="alex">alex</option>
<option value="jacob">jacob</option>
</select>
</td>
</tr>""")
def test_reverse_fk_relation_attribute(self):
alex = User.objects.create(username='alex')
jacob = User.objects.create(username='jacob')
date = now().date()
time = now().time()
Comment.objects.create(text='comment 1',
author=jacob, time=time, date=date)
Comment.objects.create(text='comment 2',
author=alex, time=time, date=date)
Comment.objects.create(text='comment 3',
author=jacob, time=time, date=date)
class F(FilterSet):
class Meta:
model = User
fields = ['comments__text']
f = F().form
self.assertHTMLEqual(six.text_type(f), """
<tr><th><label for="id_comments__text">Text:</label></th>
<td>
<input type="text" name="comments__text"
id="id_comments__text" />
</td>
</tr>""")
class F(FilterSet):
comments__text = AllValuesFilter()
class Meta:
model = User
fields = ['comments__text']
f = F().form
self.assertHTMLEqual(six.text_type(f), """
<tr>
<th>
<label for="id_comments__text">Comments text:</label>
</th>
<td>
<select name="comments__text" id="id_comments__text">
<option value="comment 1">comment 1</option>
<option value="comment 2">comment 2</option>
<option value="comment 3">comment 3</option>
</select>
</td>
</tr>""")
@unittest.skip('todo')
def test_m2m_relation(self):
pass
@unittest.skip('todo')
def test_reverse_m2m_relation(self):
pass
def test_m2m_relation_attribute(self):
alex = User.objects.create(username='alex')
User.objects.create(username='jacob')
aaron = User.objects.create(username='aaron')
b1 = Book.objects.create(title="Ender's Game", price='1.00',
average_rating=3.0)
b2 = Book.objects.create(title="Rainbow Six", price='1.00',
average_rating=3.0)
b3 = Book.objects.create(title="Snowcrash", price='1.00',
average_rating=3.0)
alex.favorite_books = [b1, b2]
aaron.favorite_books = [b1, b3]
class F(FilterSet):
class Meta:
model = User
fields = ['favorite_books__title']
f = F().form
self.assertHTMLEqual(six.text_type(f), """
<tr><th><label for="id_favorite_books__title">Title:</label></th>
<td>
<input type="text" name="favorite_books__title"
id="id_favorite_books__title" />
</td>
</tr>""")
class F(FilterSet):
favorite_books__title = MultipleChoiceFilter()
class Meta:
model = User
fields = ['favorite_books__title']
f = F().form
self.assertHTMLEqual(six.text_type(f), """
<tr><th>
<label for="id_favorite_books__title">
Favorite books title:
</label>
</th>
<td>
<select multiple="multiple" name="favorite_books__title"
id="id_favorite_books__title" />
</td>
</tr>""")
class F(FilterSet):
favorite_books__title = AllValuesFilter()
class Meta:
model = User
fields = ['favorite_books__title']
f = F().form
self.assertHTMLEqual(six.text_type(f), """
<tr><th>
<label for="id_favorite_books__title">
Favorite books title:
</label>
</th>
<td>
<select name="favorite_books__title" id="id_favorite_books__title">
<option value="None">None</option>
<option value="Ender's Game">Ender&39;s Game</option>
<option value="Rainbow Six">Rainbow Six</option>
<option value="Snowcrash">Snowcrash</option>
</select>
</td>
</tr>""")
def test_reverse_m2m_relation_attribute(self):
alex = User.objects.create(username='alex')
User.objects.create(username='jacob')
aaron = User.objects.create(username='aaron')
b1 = Book.objects.create(title="Ender's Game", price='1.00',
average_rating=3.0)
b2 = Book.objects.create(title="Rainbow Six", price='1.00',
average_rating=3.0)
b3 = Book.objects.create(title="Snowcrash", price='1.00',
average_rating=3.0)
alex.favorite_books = [b1, b2]
aaron.favorite_books = [b1, b3]
class F(FilterSet):
class Meta:
model = Book
fields = ['lovers__username']
f = F().form
self.assertHTMLEqual(six.text_type(f), """
<tr><th>
<label for="id_lovers__username">
Username:
</label>
</th>
<td>
<input type="text" name="lovers__username"
id="id_lovers__username" />
</td>
</tr>""")
class F(FilterSet):
lovers__username = AllValuesFilter()
class Meta:
model = Book
fields = ['lovers__username']
f = F().form
self.assertHTMLEqual(six.text_type(f), """
<tr><th>
<label for="id_lovers__username">
Lovers username:
</label>
</th>
<td>
<select name="lovers__username" id="id_lovers__username">
<option value="aaron">aaron</option>
<option value="alex">alex</option>
</select>
</td>
</tr>""")
@unittest.skip('todo')
def test_fk_relation_on_m2m_relation(self):
pass
@unittest.skip('todo')
def test_fk_relation_attribute_on_m2m_relation(self):
pass
class LookupTypesFilterTests(TestCase):
def test_field_output_with_multiple_lookup_types(self):
class F(FilterSet):
title = CharFilter(lookup_type=('istartswith', 'iendswith'))
class Meta:
model = Book
fields = ['title']
f = F().form['title']
self.assertHTMLEqual(six.text_type(f), '''
<input type="text" name="title_0" id="id_title_0" />
<select name="title_1" id="id_title_1">
<option value="iendswith">iendswith</option>
<option value="istartswith">istartswith</option>
</select>''')
@unittest.skip('todo')
def test_field_output_with_multiple_labeled_lookup_types(self):
class F(FilterSet):
title = CharFilter(lookup_type=(
('istartswith', 'Ends with'),
('iendswith', 'Starts with'),
))
class Meta:
model = Book
fields = ['title']
f = F().form['title']
self.assertHTMLEqual(six.text_type(f), '''
<input type="text" name="title_0" id="id_title_0" />
<select name="title_1" id="id_title_1">
<option value="iendswith">Ends with</option>
<option value="istartswith">Starts with</option>
</select>''')
def test_field_output_with_all_lookup_types(self):
class F(FilterSet):
title = CharFilter(lookup_type=None)
class Meta:
model = Book
fields = ['title']
f = F().form['title']
self.assertHTMLEqual(six.text_type(f), '''
<input type="text" name="title_0" id="id_title_0" />
<select name="title_1" id="id_title_1">
<option value="contains">contains</option>
<option value="day">day</option>
<option value="endswith">endswith</option>
<option value="exact">exact</option>
<option value="gt">gt</option>
<option value="gte">gte</option>
<option value="icontains">icontains</option>
<option value="iendswith">iendswith</option>
<option value="iexact">iexact</option>
<option value="in">in</option>
<option value="iregex">iregex</option>
<option value="isnull">isnull</option>
<option value="istartswith">istartswith</option>
<option value="lt">lt</option>
<option value="lte">lte</option>
<option value="month">month</option>
<option value="range">range</option>
<option value="regex">regex</option>
<option value="search">search</option>
<option value="startswith">startswith</option>
<option value="week_day">week_day</option>
<option value="year">year</option>
</select>''')
@unittest.expectedFailure
def test_field_output_only_shows_valid_lookup_types(self):
class F(FilterSet):
title = CharFilter(lookup_type=True)
class Meta:
model = Book
fields = ['title']
f = F().form['title']
self.assertHTMLEqual(six.text_type(f), '''
<input type="text" name="title_0" id="id_title_0" />
<select name="title_1" id="id_title_1">
<option value="contains">contains</option>
<option value="endswith">endswith</option>
<option value="exact">exact</option>
<option value="icontains">icontains</option>
<option value="iendswith">iendswith</option>
<option value="iexact">iexact</option>
<option value="in">in</option>
<option value="iregex">iregex</option>
<option value="isnull">isnull</option>
<option value="istartswith">istartswith</option>
<option value="regex">regex</option>
<option value="search">search</option>
<option value="startswith">startswith</option>
</select>''')

View File

@ -53,6 +53,14 @@ class User(models.Model):
return self.username
class AdminUser(User):
class Meta:
proxy = True
def __unicode__(self):
return "%s (ADMIN)" % self.username
class Comment(models.Model):
text = models.TextField()
author = models.ForeignKey(User, related_name='comments')
@ -113,3 +121,19 @@ class Location(models.Model):
def __unicode__(self):
return '%s: %s' % (self.company.name, self.name)
class Account(models.Model):
name = models.CharField(max_length=100)
in_good_standing = models.BooleanField()
friendly = models.BooleanField()
class Profile(models.Model):
account = models.OneToOneField(Account, related_name='profile')
likes_coffee = models.BooleanField()
likes_tea = models.BooleanField()
class BankAccount(Account):
amount_saved = models.IntegerField(default=0)

View File

@ -1,7 +1,12 @@
from __future__ import absolute_import
from __future__ import unicode_literals
from django.core.exceptions import ImproperlyConfigured
from django.test import TestCase
from django.test.client import RequestFactory
from django_filters.views import FilterView
from django_filters.filterset import FilterSet, filterset_factory
from .models import Book
@ -32,6 +37,33 @@ class GenericClassBasedViewTests(GenericViewTestCase):
self.assertNotContains(response, b)
self.assertContains(response, 'Snowcrash')
def test_view_with_filterset_not_model(self):
factory = RequestFactory()
request = factory.get(self.base_url)
filterset = filterset_factory(Book)
view = FilterView.as_view(filterset_class=filterset)
response = view(request)
self.assertEqual(response.status_code, 200)
for b in ['Ender&#39;s Game', 'Rainbow Six', 'Snowcrash']:
self.assertContains(response, b)
def test_view_without_filterset_or_model(self):
factory = RequestFactory()
request = factory.get(self.base_url)
view = FilterView.as_view()
with self.assertRaises(ImproperlyConfigured):
view(request)
def test_view_with_bad_filterset(self):
class MyFilterSet(FilterSet):
pass
factory = RequestFactory()
request = factory.get(self.base_url)
view = FilterView.as_view(filterset_class=MyFilterSet)
with self.assertRaises(ImproperlyConfigured):
view(request)
class GenericFunctionalViewTests(GenericViewTestCase):
base_url = '/books-legacy/'

View File

@ -2,6 +2,7 @@ from __future__ import absolute_import
from __future__ import unicode_literals
from django.test import TestCase
from django.forms import TextInput, Select
from django_filters.widgets import RangeWidget
from django_filters.widgets import LinkWidget
@ -14,6 +15,30 @@ class LookupTypeWidgetTests(TestCase):
with self.assertRaises(TypeError):
LookupTypeWidget()
def test_widget_render(self):
widgets = [TextInput(), Select(choices=(('a', 'a'), ('b', 'b')))]
w = LookupTypeWidget(widgets)
self.assertHTMLEqual(w.render('price', ''), """
<input name="price_0" type="text" />
<select name="price_1">
<option value="a">a</option>
<option value="b">b</option>
</select>""")
self.assertHTMLEqual(w.render('price', None), """
<input name="price_0" type="text" />
<select name="price_1">
<option value="a">a</option>
<option value="b">b</option>
</select>""")
self.assertHTMLEqual(w.render('price', ['2', 'a']), """
<input name="price_0" type="text" value="2" />
<select name="price_1">
<option selected="selected" value="a">a</option>
<option value="b">b</option>
</select>""")
class LinkWidgetTests(TestCase):
@ -35,6 +60,12 @@ class LinkWidgetTests(TestCase):
<li><a href="?price=test-val2">test-label2</a></li>
</ul>""")
self.assertHTMLEqual(w.render('price', None), """
<ul>
<li><a href="?price=test-val1">test-label1</a></li>
<li><a href="?price=test-val2">test-label2</a></li>
</ul>""")
self.assertHTMLEqual(w.render('price', 'test-val1'), """
<ul>
<li><a class="selected"
@ -42,6 +73,52 @@ class LinkWidgetTests(TestCase):
<li><a href="?price=test-val2">test-label2</a></li>
</ul>""")
def test_widget_with_option_groups(self):
choices = (
('Audio', (
('vinyl', 'Vinyl'),
('cd', 'CD'),
)
),
('Video', (
('vhs', 'VHS Tape'),
('dvd', 'DVD'),
)
),
('unknown', 'Unknown'),
)
w = LinkWidget(choices=choices)
self.assertHTMLEqual(w.render('media', ''), """
<ul>
<li><a href="?media=vinyl">Vinyl</a></li>
<li><a href="?media=cd">CD</a></li>
<li><a href="?media=vhs">VHS Tape</a></li>
<li><a href="?media=dvd">DVD</a></li>
<li><a href="?media=unknown">Unknown</a></li>
</ul>""")
def test_widget_with_blank_choice(self):
choices = (
('', '---------'),
('test-val1', 'test-label1'),
('test-val2', 'test-label2'),
)
w = LinkWidget(choices=choices)
self.assertHTMLEqual(w.render('price', ''), """
<ul>
<li><a class="selected" href="?price=">All</a></li>
<li><a href="?price=test-val1">test-label1</a></li>
<li><a href="?price=test-val2">test-label2</a></li>
</ul>""")
def test_widget_value_from_datadict(self):
w = LinkWidget()
data = {'price': 'test-val1'}
result = w.value_from_datadict(data, {}, 'price')
self.assertEqual(result, 'test-val1')
class RangeWidgetTests(TestCase):