Merge branch 'develop' into django-compatibility-updates
Conflicts: .travis.yml README.rst django_filters/fields.py
This commit is contained in:
commit
fd425e64ed
17
.travis.yml
17
.travis.yml
|
@ -11,9 +11,8 @@ python:
|
|||
|
||||
env:
|
||||
- DJANGO='https://github.com/django/django/archive/master.tar.gz'
|
||||
- DJANGO='https://www.djangoproject.com/download/1.9a1/tarball/'
|
||||
- DJANGO='https://www.djangoproject.com/download/1.9rc1/tarball/'
|
||||
- DJANGO='django>=1.8.0,<1.9.0'
|
||||
- DJANGO='django>=1.7.0,<1.8.0'
|
||||
|
||||
install:
|
||||
- travis_retry pip install $DJANGO
|
||||
|
@ -31,21 +30,11 @@ matrix:
|
|||
- python: "3.2"
|
||||
env: DJANGO='https://github.com/django/django/archive/master.tar.gz'
|
||||
- python: "3.2"
|
||||
env: DJANGO='https://www.djangoproject.com/download/1.9a1/tarball/'
|
||||
env: DJANGO='https://www.djangoproject.com/download/1.9rc1/tarball/'
|
||||
- python: "3.3"
|
||||
env: DJANGO='https://github.com/django/django/archive/master.tar.gz'
|
||||
- python: "3.3"
|
||||
env: DJANGO='https://www.djangoproject.com/download/1.9a1/tarball/'
|
||||
- python: "3.5"
|
||||
env: DJANGO='django>=1.7.0,<1.8.0'
|
||||
- python: "2.6"
|
||||
env: DJANGO='django>=1.7.0,<1.8.0'
|
||||
- python: "2.6"
|
||||
env: DJANGO='django>=1.8.0,<1.9.0'
|
||||
- python: "2.6"
|
||||
env: DJANGO='https://github.com/django/django/archive/master.tar.gz'
|
||||
- python: "2.6"
|
||||
env: DJANGO='https://www.djangoproject.com/download/1.9a1/tarball/'
|
||||
env: DJANGO='https://www.djangoproject.com/download/1.9rc1/tarball/'
|
||||
allow_failures:
|
||||
- env: DJANGO='https://github.com/django/django/archive/master.tar.gz'
|
||||
fast_finish: true
|
||||
|
|
|
@ -13,7 +13,7 @@ Requirements
|
|||
------------
|
||||
|
||||
* Python 2.7, 3.2, 3.3, 3.4, 3.5
|
||||
* Django 1.7, 1.8, 1.9
|
||||
* Django 1.8, 1.9
|
||||
|
||||
Installation
|
||||
------------
|
||||
|
|
|
@ -13,15 +13,6 @@ from django.utils.encoding import force_str
|
|||
|
||||
from .widgets import RangeWidget, LookupTypeWidget
|
||||
|
||||
try:
|
||||
from django.forms import UUIDField
|
||||
except ImportError as e:
|
||||
uuidfield_import_error = e
|
||||
class UUIDField(object):
|
||||
def __init__(self, *args, **kwargs):
|
||||
# delay ImportError until it is used
|
||||
raise uuidfield_import_error
|
||||
|
||||
|
||||
class RangeField(forms.MultiValueField):
|
||||
widget = RangeWidget
|
||||
|
|
|
@ -12,7 +12,7 @@ from django.utils.timezone import now
|
|||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from .fields import (
|
||||
RangeField, LookupTypeField, Lookup, DateRangeField, TimeRangeField, IsoDateTimeField, UUIDField)
|
||||
RangeField, LookupTypeField, Lookup, DateRangeField, TimeRangeField, IsoDateTimeField)
|
||||
|
||||
|
||||
__all__ = [
|
||||
|
@ -107,7 +107,7 @@ class TypedChoiceFilter(Filter):
|
|||
|
||||
|
||||
class UUIDFilter(Filter):
|
||||
field_class = UUIDField
|
||||
field_class = forms.UUIDField
|
||||
|
||||
|
||||
class MultipleChoiceFilter(Filter):
|
||||
|
|
|
@ -4,36 +4,20 @@ from __future__ import unicode_literals
|
|||
import types
|
||||
import copy
|
||||
import re
|
||||
from collections import OrderedDict
|
||||
|
||||
from django import forms
|
||||
from django.forms.forms import NON_FIELD_ERRORS
|
||||
from django.core.validators import EMPTY_VALUES
|
||||
from django.db import models
|
||||
from django.db.models.constants import LOOKUP_SEP
|
||||
from django.db.models.fields import FieldDoesNotExist
|
||||
from django.db.models.fields.related import ForeignObjectRel
|
||||
from django.utils import six
|
||||
from django.utils.text import capfirst
|
||||
from django.utils.translation import ugettext as _
|
||||
from sys import version_info
|
||||
|
||||
try:
|
||||
from django.db.models.constants import LOOKUP_SEP
|
||||
except ImportError: # pragma: nocover
|
||||
# Django < 1.5 fallback
|
||||
from django.db.models.sql.constants import LOOKUP_SEP # noqa
|
||||
|
||||
try:
|
||||
from collections import OrderedDict
|
||||
except ImportError: # pragma: nocover
|
||||
# Django < 1.5 fallback
|
||||
from django.utils.datastructures import SortedDict as OrderedDict # noqa
|
||||
|
||||
try:
|
||||
from django.db.models.related import RelatedObject as ForeignObjectRel
|
||||
except ImportError: # pragma: nocover
|
||||
# Django >= 1.8 replaces RelatedObject with ForeignObjectRel
|
||||
from django.db.models.fields.related import ForeignObjectRel
|
||||
|
||||
|
||||
from .filters import (Filter, CharFilter, BooleanFilter,
|
||||
ChoiceFilter, DateFilter, DateTimeFilter, TimeFilter, ModelChoiceFilter,
|
||||
ModelMultipleChoiceFilter, NumberFilter, UUIDFilter)
|
||||
|
@ -300,6 +284,9 @@ FILTER_FOR_DBFIELD_DEFAULTS = {
|
|||
models.IPAddressField: {
|
||||
'filter_class': CharFilter,
|
||||
},
|
||||
models.GenericIPAddressField: {
|
||||
'filter_class': CharFilter,
|
||||
},
|
||||
models.CommaSeparatedIntegerField: {
|
||||
'filter_class': CharFilter,
|
||||
},
|
||||
|
@ -340,7 +327,7 @@ class BaseFilterSet(object):
|
|||
yield obj
|
||||
|
||||
def __len__(self):
|
||||
return len(self.qs)
|
||||
return self.qs.count()
|
||||
|
||||
def __getitem__(self, key):
|
||||
return self.qs[key]
|
||||
|
|
Binary file not shown.
|
@ -0,0 +1,47 @@
|
|||
# Django Filter translation.
|
||||
# Copyright (C) 2013
|
||||
# This file is distributed under the same license as the django_filter package.
|
||||
# Gonzalo Bustos, 2015.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2013-07-05 19:24+0200\n"
|
||||
"PO-Revision-Date: 2015-10-11 20:53-0300\n"
|
||||
"Last-Translator: Gonzalo Bustos\n"
|
||||
"Language-Team: Spanish (Argentina)\n"
|
||||
"Language: es_AR\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"X-Generator: Poedit 1.6.10\n"
|
||||
|
||||
#: filters.py:51
|
||||
msgid "This is an exclusion filter"
|
||||
msgstr "Este es un filtro de exclusión"
|
||||
|
||||
#: filters.py:158
|
||||
msgid "Any date"
|
||||
msgstr "Cualquier fecha"
|
||||
|
||||
#: filters.py:159
|
||||
msgid "Today"
|
||||
msgstr "Hoy"
|
||||
|
||||
#: filters.py:164
|
||||
msgid "Past 7 days"
|
||||
msgstr "Últimos 7 días"
|
||||
|
||||
#: filters.py:168
|
||||
msgid "This month"
|
||||
msgstr "Este mes"
|
||||
|
||||
#: filters.py:172
|
||||
msgid "This year"
|
||||
msgstr "Este año"
|
||||
|
||||
#: widgets.py:63
|
||||
msgid "All"
|
||||
msgstr "Todos"
|
|
@ -10,10 +10,7 @@ except:
|
|||
from django import forms
|
||||
from django.db.models.fields import BLANK_CHOICE_DASH
|
||||
from django.forms.widgets import flatatt
|
||||
try:
|
||||
from django.utils.encoding import force_text
|
||||
except: # pragma: nocover
|
||||
from django.utils.encoding import force_unicode as force_text # noqa
|
||||
from django.utils.encoding import force_text
|
||||
from django.utils.safestring import mark_safe
|
||||
from django.utils.translation import ugettext as _
|
||||
|
||||
|
@ -80,7 +77,7 @@ class LinkWidget(forms.Widget):
|
|||
|
||||
class RangeWidget(forms.MultiWidget):
|
||||
def __init__(self, attrs=None):
|
||||
widgets = (forms.TextInput(attrs=attrs), forms.TextInput(attrs=attrs))
|
||||
widgets = (forms.TextInput, forms.TextInput)
|
||||
super(RangeWidget, self).__init__(widgets, attrs)
|
||||
|
||||
def decompress(self, value):
|
||||
|
|
|
@ -278,7 +278,7 @@ to the widgets that are included with Django that you can use there are
|
|||
additional ones that django-filter provides which may be useful:
|
||||
|
||||
* ``django_filters.widgets.LinkWidget`` -- this displays the options in a
|
||||
mannner similar to the way the Django Admin does, as a series of links.
|
||||
manner similar to the way the Django Admin does, as a series of links.
|
||||
The link for the selected option will have ``class="selected"``.
|
||||
|
||||
``action``
|
||||
|
|
|
@ -150,7 +150,7 @@ Though you would need to pass in the actual function value, not it's name.
|
|||
|
||||
class F(django_filters.FilterSet):
|
||||
# Notice: In this case, action accepts a func, not a string
|
||||
username = MethodFilter(action=filter_username)
|
||||
username = MethodFilter(action=my_custom_filter)
|
||||
|
||||
class Meta:
|
||||
model = User
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
#!/usr/bin/env python
|
||||
import sys
|
||||
from django.conf import settings
|
||||
from django.core.management import call_command
|
||||
from django.core.management import execute_from_command_line
|
||||
|
||||
if not settings.configured:
|
||||
|
@ -23,7 +22,7 @@ if not settings.configured:
|
|||
|
||||
|
||||
def runshell():
|
||||
call_command('syncdb', interactive=False)
|
||||
execute_from_command_line(sys.argv[:1] + ['syncdb', '--noinput', '-v', '0'])
|
||||
argv = sys.argv[:1] + ['shell'] + sys.argv[1:]
|
||||
execute_from_command_line(argv)
|
||||
|
||||
|
|
|
@ -3,40 +3,22 @@ from __future__ import unicode_literals
|
|||
|
||||
from datetime import datetime, time, timedelta, tzinfo
|
||||
import decimal
|
||||
import sys
|
||||
|
||||
if sys.version_info >= (2, 7):
|
||||
import unittest
|
||||
else: # pragma: nocover
|
||||
from django.utils import unittest # noqa
|
||||
import unittest
|
||||
|
||||
import django
|
||||
from django import forms
|
||||
from django.test import TestCase
|
||||
try:
|
||||
from django.test import override_settings
|
||||
except ImportError:
|
||||
# TODO: Remove this once Django 1.6 is EOL.
|
||||
from django.test.utils import override_settings
|
||||
from django.test import TestCase, override_settings
|
||||
from django.utils.timezone import make_aware
|
||||
|
||||
from django_filters.widgets import RangeWidget
|
||||
from django_filters.fields import (
|
||||
RangeField, LookupTypeField, Lookup, DateRangeField, TimeRangeField, IsoDateTimeField, UUIDField)
|
||||
RangeField, LookupTypeField, Lookup, DateRangeField, TimeRangeField, IsoDateTimeField)
|
||||
|
||||
|
||||
def to_d(float_value):
|
||||
return decimal.Decimal('%.2f' % float_value)
|
||||
|
||||
|
||||
class UUIDFieldTests(TestCase):
|
||||
|
||||
def test_field(self):
|
||||
if django.VERSION < (1, 8):
|
||||
with self.assertRaises(ImportError):
|
||||
UUIDField()
|
||||
else:
|
||||
self.assertIs(UUIDField, forms.UUIDField)
|
||||
|
||||
|
||||
class RangeFieldTests(TestCase):
|
||||
|
||||
def test_field(self):
|
||||
|
@ -156,7 +138,7 @@ class IsoDateTimeFieldTests(TestCase):
|
|||
def test_datetime_timezone_awareness(self):
|
||||
# parsed datetimes should obey USE_TZ
|
||||
f = IsoDateTimeField()
|
||||
r = self.reference_dt.replace(tzinfo=f.default_timezone)
|
||||
r = make_aware(self.reference_dt, f.default_timezone)
|
||||
|
||||
d = f.strptime(self.reference_str + "+01:00", IsoDateTimeField.ISO_8601)
|
||||
self.assertTrue(isinstance(d.tzinfo, tzinfo))
|
||||
|
|
|
@ -3,12 +3,7 @@ from __future__ import unicode_literals
|
|||
|
||||
import datetime
|
||||
import mock
|
||||
import sys
|
||||
|
||||
if sys.version_info >= (2, 7):
|
||||
import unittest
|
||||
else: # pragma: nocover
|
||||
from django.utils import unittest # noqa
|
||||
import unittest
|
||||
|
||||
from django.test import TestCase
|
||||
from django.utils import six
|
||||
|
@ -1331,4 +1326,3 @@ class MiscFilterSetTests(TestCase):
|
|||
f = F({'status': '2'}, queryset=qs)
|
||||
self.assertEqual(len(f.qs), 2)
|
||||
self.assertEqual(f.count(), 2)
|
||||
|
||||
|
|
|
@ -1,16 +1,9 @@
|
|||
from __future__ import absolute_import
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from datetime import date, datetime, time
|
||||
from datetime import date, time, timedelta
|
||||
import mock
|
||||
import sys
|
||||
|
||||
if sys.version_info >= (2, 7):
|
||||
import unittest
|
||||
else: # pragma: nocover
|
||||
from django.utils import unittest # noqa
|
||||
|
||||
from datetime import timedelta
|
||||
import unittest
|
||||
|
||||
import django
|
||||
from django import forms
|
||||
|
@ -22,8 +15,7 @@ from django_filters.fields import (
|
|||
RangeField,
|
||||
DateRangeField,
|
||||
TimeRangeField,
|
||||
LookupTypeField,
|
||||
UUIDField)
|
||||
LookupTypeField)
|
||||
from django_filters.filters import (
|
||||
Filter,
|
||||
CharFilter,
|
||||
|
@ -210,7 +202,7 @@ class UUIDFilterTests(TestCase):
|
|||
if not django.VERSION < (1, 8):
|
||||
f = UUIDFilter()
|
||||
field = f.field
|
||||
self.assertIsInstance(field, UUIDField)
|
||||
self.assertIsInstance(field, forms.UUIDField)
|
||||
else:
|
||||
with self.assertRaises(ImportError):
|
||||
UUIDFilter().field
|
||||
|
|
|
@ -1,12 +1,7 @@
|
|||
from __future__ import absolute_import, unicode_literals
|
||||
|
||||
import mock
|
||||
import sys
|
||||
|
||||
if sys.version_info >= (2, 7):
|
||||
import unittest
|
||||
else: # pragma: nocover
|
||||
from django.utils import unittest # noqa
|
||||
import unittest
|
||||
|
||||
import django
|
||||
from django.db import models
|
||||
|
@ -46,6 +41,7 @@ def checkItemsEqual(L1, L2):
|
|||
"""
|
||||
return len(L1) == len(L2) and sorted(L1) == sorted(L2)
|
||||
|
||||
|
||||
class HelperMethodsTests(TestCase):
|
||||
|
||||
@unittest.skip('todo')
|
||||
|
@ -84,6 +80,7 @@ class DbFieldDefaultFiltersTests(TestCase):
|
|||
models.FloatField,
|
||||
models.IntegerField,
|
||||
models.IPAddressField,
|
||||
models.GenericIPAddressField,
|
||||
models.NullBooleanField,
|
||||
models.PositiveIntegerField,
|
||||
models.PositiveSmallIntegerField,
|
||||
|
@ -107,7 +104,6 @@ class DbFieldDefaultFiltersTests(TestCase):
|
|||
to_check = [
|
||||
models.Field,
|
||||
models.BigIntegerField,
|
||||
models.GenericIPAddressField,
|
||||
models.FileField,
|
||||
models.ImageField,
|
||||
]
|
||||
|
|
|
@ -136,6 +136,14 @@ class RangeWidgetTests(TestCase):
|
|||
-
|
||||
<input type="text" name="price_1" value="9.99" />""")
|
||||
|
||||
def test_widget_attributes(self):
|
||||
w = RangeWidget(attrs={'type': 'date'})
|
||||
self.assertEqual(len(w.widgets), 2)
|
||||
self.assertHTMLEqual(w.render('date', ''), """
|
||||
<input type="date" name="date_0" />
|
||||
-
|
||||
<input type="date" name="date_1" />""")
|
||||
|
||||
|
||||
class BooleanWidgetTests(TestCase):
|
||||
"""
|
||||
|
|
Loading…
Reference in New Issue